This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- get_tab_bar_item_kbd
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- pad_mode_line
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- gui_union_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 #include <config.h>
434 #include <stdlib.h>
435 #include <limits.h>
436 #include <math.h>
437
438 #include "lisp.h"
439 #include "atimer.h"
440 #include "composite.h"
441 #include "keyboard.h"
442 #include "sysstdio.h"
443 #include "systime.h"
444 #include "frame.h"
445 #include "window.h"
446 #include "termchar.h"
447 #include "dispextern.h"
448 #include "character.h"
449 #include "category.h"
450 #include "buffer.h"
451 #include "charset.h"
452 #include "indent.h"
453 #include "commands.h"
454 #include "keymap.h"
455 #include "disptab.h"
456 #include "termhooks.h"
457 #include "termopts.h"
458 #include "intervals.h"
459 #include "coding.h"
460 #include "region-cache.h"
461 #include "font.h"
462 #include "fontset.h"
463 #include "blockinput.h"
464 #include "xwidget.h"
465 #ifdef HAVE_WINDOW_SYSTEM
466 #include TERM_HEADER
467 #endif
468
469 #ifndef FRAME_OUTPUT_DATA
470 #define FRAME_OUTPUT_DATA(f) (NULL)
471 #endif
472
473 #define DISP_INFINITY 10000000
474
475
476 static Lisp_Object list_of_error;
477
478 #ifdef HAVE_WINDOW_SYSTEM
479
480
481
482
483 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
484 (!NILP (Voverflow_newline_into_fringe) \
485 && FRAME_WINDOW_P ((IT)->f) \
486 && ((IT)->bidi_it.paragraph_dir == R2L \
487 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
488 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
489 && (IT)->current_x == (IT)->last_visible_x)
490
491 #else
492 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
493 #endif
494
495
496
497
498
499 #define IT_DISPLAYING_WHITESPACE(it) \
500 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
501 || ((STRINGP (it->string) \
502 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
503 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
504 || (it->s \
505 && (it->s[IT_BYTEPOS (*it)] == ' ' \
506 || it->s[IT_BYTEPOS (*it)] == '\t')) \
507 || (IT_BYTEPOS (*it) < ZV_BYTE \
508 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
509 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
510
511
512
513 #define NOT_AT_EOL '<'
514 #define NOT_AT_BOL '>'
515 #define LINE_BREAKABLE '|'
516
517 static bool
518 it_char_has_category(struct it *it, int cat)
519 {
520 int ch = 0;
521 if (it->what == IT_CHARACTER)
522 ch = it->c;
523 else if (STRINGP (it->string))
524 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
525 else if (it->s)
526 ch = it->s[IT_BYTEPOS (*it)];
527 else if (IT_BYTEPOS (*it) < ZV_BYTE)
528 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
529
530 if (ch == 0)
531 return false;
532 else
533 return CHAR_HAS_CATEGORY (ch, cat);
534 }
535
536
537 static bool
538 char_can_wrap_before (struct it *it)
539 {
540 if (!word_wrap_by_category)
541 return !IT_DISPLAYING_WHITESPACE (it);
542
543
544
545
546 int not_at_bol;
547 if (it->glyph_row && it->glyph_row->reversed_p)
548 not_at_bol = NOT_AT_EOL;
549 else
550 not_at_bol = NOT_AT_BOL;
551
552
553 return (!IT_DISPLAYING_WHITESPACE (it)
554
555 && !it_char_has_category (it, not_at_bol));
556 }
557
558
559 static bool
560 char_can_wrap_after (struct it *it)
561 {
562 if (!word_wrap_by_category)
563 return IT_DISPLAYING_WHITESPACE (it);
564
565
566
567
568 int not_at_eol;
569 if (it->glyph_row && it->glyph_row->reversed_p)
570 not_at_eol = NOT_AT_BOL;
571 else
572 not_at_eol = NOT_AT_EOL;
573
574 return (IT_DISPLAYING_WHITESPACE (it)
575
576 || (it_char_has_category (it, LINE_BREAKABLE)
577 && !it_char_has_category (it, not_at_eol)));
578 }
579
580 #undef IT_DISPLAYING_WHITESPACE
581 #undef NOT_AT_EOL
582 #undef NOT_AT_BOL
583 #undef LINE_BREAKABLE
584
585
586
587
588 static int
589 fill_column_indicator_column (struct it *it, int char_width)
590 {
591 if (display_fill_column_indicator
592 && !it->w->pseudo_window_p
593 && it->continuation_lines_width == 0
594 && CHARACTERP (Vdisplay_fill_column_indicator_character))
595 {
596 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
597 ? BVAR (current_buffer, fill_column)
598 : Vdisplay_fill_column_indicator_column);
599
600
601
602 if (RANGED_FIXNUMP (0, col, INT_MAX))
603 {
604 int icol = XFIXNUM (col);
605 if (!ckd_mul (&icol, icol, char_width)
606 && !ckd_add (&icol, icol, it->lnum_pixel_width))
607 return icol;
608 }
609 }
610 return -1;
611 }
612
613
614
615 bool noninteractive_need_newline;
616
617
618
619 static bool message_log_need_newline;
620
621
622
623
624 static Lisp_Object message_dolog_marker1;
625 static Lisp_Object message_dolog_marker2;
626 static Lisp_Object message_dolog_marker3;
627
628
629
630
631
632
633 static struct text_pos this_line_start_pos;
634
635
636
637
638 static struct text_pos this_line_end_pos;
639
640
641
642 static int this_line_vpos;
643 static int this_line_y;
644 static int this_line_pixel_height;
645
646
647
648
649 static int this_line_start_x;
650
651
652
653
654
655 static struct text_pos this_line_min_pos;
656
657
658
659 static struct buffer *this_line_buffer;
660
661
662
663 static bool overlay_arrow_seen;
664
665
666
667 static Lisp_Object default_invis_vector[3];
668
669
670
671
672
673 Lisp_Object echo_area_window;
674
675
676
677
678 static Lisp_Object Vmessage_stack;
679
680
681
682
683 static bool message_enable_multibyte;
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 int windows_or_buffers_changed;
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736 int update_mode_lines;
737
738
739
740
741 static bool line_number_displayed;
742
743
744
745
746 Lisp_Object echo_area_buffer[2];
747
748
749
750 static Lisp_Object echo_buffer[2];
751
752
753
754 static Lisp_Object Vwith_echo_area_save_vector;
755
756
757
758
759 static bool display_last_displayed_message_p;
760
761
762
763
764 static bool message_buf_print;
765
766
767
768
769 static bool message_cleared_p;
770
771
772
773
774 #define MAX_SCRATCH_GLYPHS 100
775 static struct glyph_row scratch_glyph_row;
776 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
777
778
779
780 static int last_height;
781
782
783
784 bool help_echo_showing_p;
785
786
787
788
789
790
791
792 #define TEXT_PROP_DISTANCE_LIMIT 100
793
794
795
796
797
798
799
800
801 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
802 do { \
803 if (CACHE) \
804 bidi_unshelve_cache (CACHE, true); \
805 ITCOPY = ITORIG; \
806 CACHE = bidi_shelve_cache (); \
807 } while (false)
808
809 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
810 do { \
811 if (pITORIG != pITCOPY) \
812 *(pITORIG) = *(pITCOPY); \
813 bidi_unshelve_cache (CACHE, false); \
814 CACHE = NULL; \
815 } while (false)
816
817
818 enum { REDISPLAY_SOME = 2};
819
820 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
821 struct font *, bool, int *);
822
823 void
824 redisplay_other_windows (void)
825 {
826 if (!windows_or_buffers_changed)
827 windows_or_buffers_changed = REDISPLAY_SOME;
828 }
829
830 void
831 wset_redisplay (struct window *w)
832 {
833
834 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
835 redisplay_other_windows ();
836 w->redisplay = true;
837 }
838
839 void
840 fset_redisplay (struct frame *f)
841 {
842 redisplay_other_windows ();
843 f->redisplay = true;
844 }
845
846 void
847 bset_redisplay (struct buffer *b)
848 {
849 int count = buffer_window_count (b);
850 if (count > 0)
851 {
852
853 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
854 redisplay_other_windows ();
855
856
857
858 b->text->redisplay = true;
859 }
860 }
861
862 void
863 bset_update_mode_line (struct buffer *b)
864 {
865 if (!update_mode_lines)
866 update_mode_lines = REDISPLAY_SOME;
867 b->text->redisplay = true;
868 }
869
870 void
871 wset_update_mode_line (struct window *w)
872 {
873 w->update_mode_line = true;
874
875
876
877
878
879
880 wset_redisplay (w);
881 }
882
883 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
884 Sset_buffer_redisplay, 4, 4, 0,
885 doc:
886 )
887 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
888 {
889 bset_update_mode_line (current_buffer);
890 current_buffer->prevent_redisplay_optimizations_p = true;
891 return Qnil;
892 }
893
894
895
896
897
898 #ifdef GLYPH_DEBUG
899 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
900 bool trace_redisplay_p;
901 #else
902 enum { trace_redisplay_p = false };
903 #endif
904 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
905 redisplay_trace (char const *fmt, ...)
906 {
907 if (trace_redisplay_p)
908 {
909 va_list ap;
910 va_start (ap, fmt);
911 vprintf (fmt, ap);
912 va_end (ap);
913 }
914 }
915
916 #ifdef DEBUG_TRACE_MOVE
917 extern bool trace_move EXTERNALLY_VISIBLE;
918 bool trace_move;
919 #else
920 enum { trace_move = false };
921 #endif
922 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
923 move_trace (char const *fmt, ...)
924 {
925 if (trace_move)
926 {
927 va_list ap;
928 va_start (ap, fmt);
929 vprintf (fmt, ap);
930 va_end (ap);
931 }
932 }
933
934
935
936 static struct buffer *displayed_buffer;
937
938
939
940 enum prop_handled
941 {
942 HANDLED_NORMALLY,
943 HANDLED_RECOMPUTE_PROPS,
944 HANDLED_OVERLAY_STRING_CONSUMED,
945 HANDLED_RETURN
946 };
947
948
949
950
951 struct props
952 {
953
954 short name;
955
956
957 enum prop_idx idx;
958
959
960
961 enum prop_handled (*handler) (struct it *it);
962 };
963
964 static enum prop_handled handle_face_prop (struct it *);
965 static enum prop_handled handle_invisible_prop (struct it *);
966 static enum prop_handled handle_display_prop (struct it *);
967 static enum prop_handled handle_composition_prop (struct it *);
968 static enum prop_handled handle_overlay_change (struct it *);
969 static enum prop_handled handle_fontified_prop (struct it *);
970
971
972
973 static struct props it_props[] =
974 {
975 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
976
977
978 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
979 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
980 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
981 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
982 {0, 0, NULL}
983 };
984
985
986
987 enum move_it_result
988 {
989
990 MOVE_UNDEFINED,
991
992
993 MOVE_POS_MATCH_OR_ZV,
994
995
996 MOVE_X_REACHED,
997
998
999
1000 MOVE_LINE_CONTINUED,
1001
1002
1003
1004 MOVE_LINE_TRUNCATED,
1005
1006
1007 MOVE_NEWLINE_OR_CR
1008 };
1009
1010
1011
1012
1013
1014
1015 #define CLEAR_FACE_CACHE_COUNT 500
1016 static int clear_face_cache_count;
1017
1018
1019
1020 #ifdef HAVE_WINDOW_SYSTEM
1021 #define CLEAR_IMAGE_CACHE_COUNT 101
1022 static int clear_image_cache_count;
1023
1024
1025 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1026 #endif
1027
1028
1029
1030 bool redisplaying_p;
1031
1032
1033
1034
1035
1036
1037
1038
1039 bool display_working_on_window_p;
1040
1041
1042
1043
1044 Lisp_Object help_echo_string;
1045 Lisp_Object help_echo_window;
1046 Lisp_Object help_echo_object;
1047 ptrdiff_t help_echo_pos;
1048
1049
1050
1051 Lisp_Object previous_help_echo_string;
1052
1053
1054
1055 #ifdef HAVE_WINDOW_SYSTEM
1056
1057
1058 static bool hourglass_shown_p;
1059
1060
1061
1062 static struct atimer *hourglass_atimer;
1063
1064 #endif
1065
1066
1067
1068 #define DEFAULT_HOURGLASS_DELAY 1
1069
1070 #ifdef HAVE_WINDOW_SYSTEM
1071
1072
1073 #define THIN_SPACE_WIDTH 1
1074
1075 #endif
1076
1077
1078
1079 static void setup_for_ellipsis (struct it *, int);
1080 static void set_iterator_to_next (struct it *, bool);
1081 static void mark_window_display_accurate_1 (struct window *, bool);
1082 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1083 static bool cursor_row_p (struct glyph_row *);
1084 static int redisplay_mode_lines (Lisp_Object, bool);
1085
1086 static void handle_line_prefix (struct it *);
1087
1088 static void handle_stop_backwards (struct it *, ptrdiff_t);
1089 static void unwind_with_echo_area_buffer (Lisp_Object);
1090 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1091 static bool current_message_1 (void *, Lisp_Object);
1092 static bool truncate_message_1 (void *, Lisp_Object);
1093 static void set_message (Lisp_Object);
1094 static bool set_message_1 (void *, Lisp_Object);
1095 static bool display_echo_area_1 (void *, Lisp_Object);
1096 static bool resize_mini_window_1 (void *, Lisp_Object);
1097 static void unwind_redisplay (void);
1098 static void extend_face_to_end_of_line (struct it *);
1099 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1100 static void push_it (struct it *, struct text_pos *);
1101 static void iterate_out_of_display_property (struct it *);
1102 static void pop_it (struct it *);
1103 static void redisplay_internal (void);
1104 static void echo_area_display (bool);
1105 static void block_buffer_flips (void);
1106 static void unblock_buffer_flips (void);
1107 static void redisplay_windows (Lisp_Object);
1108 static void redisplay_window (Lisp_Object, bool);
1109 static Lisp_Object redisplay_window_error (Lisp_Object);
1110 static Lisp_Object redisplay_window_0 (Lisp_Object);
1111 static Lisp_Object redisplay_window_1 (Lisp_Object);
1112 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1113 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1114 int, int);
1115 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1116 static bool update_menu_bar (struct frame *, bool, bool);
1117 static bool try_window_reusing_current_matrix (struct window *);
1118 static int try_window_id (struct window *);
1119 static void maybe_produce_line_number (struct it *);
1120 static bool should_produce_line_number (struct it *);
1121 static bool display_line (struct it *, int);
1122 static int display_mode_lines (struct window *);
1123 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1124 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1125 Lisp_Object, bool);
1126 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1127 Lisp_Object);
1128 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1129 static void display_menu_bar (struct window *);
1130 static void display_tab_bar (struct window *);
1131 static void update_tab_bar (struct frame *, bool);
1132 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1133 ptrdiff_t *);
1134 static void pint2str (register char *, register int, register ptrdiff_t);
1135
1136 static int display_string (const char *, Lisp_Object, Lisp_Object,
1137 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1138 int);
1139 static void compute_line_metrics (struct it *);
1140 static bool get_overlay_strings (struct it *, ptrdiff_t);
1141 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1142 static void next_overlay_string (struct it *);
1143 static void reseat (struct it *, struct text_pos, bool);
1144 static void reseat_1 (struct it *, struct text_pos, bool);
1145 static bool next_element_from_display_vector (struct it *);
1146 static bool next_element_from_string (struct it *);
1147 static bool next_element_from_c_string (struct it *);
1148 static bool next_element_from_buffer (struct it *);
1149 static bool next_element_from_composition (struct it *);
1150 static bool next_element_from_image (struct it *);
1151 static bool next_element_from_stretch (struct it *);
1152 static bool next_element_from_xwidget (struct it *);
1153 static void load_overlay_strings (struct it *, ptrdiff_t);
1154 static bool get_next_display_element (struct it *);
1155 static enum move_it_result
1156 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1157 enum move_operation_enum);
1158 static void get_visually_first_element (struct it *);
1159 static void compute_stop_pos (struct it *);
1160 static int face_before_or_after_it_pos (struct it *, bool);
1161 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1162 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1163 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1164 Lisp_Object, struct text_pos *,
1165 ptrdiff_t, int, bool, bool);
1166 static int underlying_face_id (const struct it *);
1167
1168 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1169 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1170
1171 #ifdef HAVE_WINDOW_SYSTEM
1172
1173 static void update_tool_bar (struct frame *, bool);
1174 static void gui_draw_bottom_divider (struct window *w);
1175 static void notice_overwritten_cursor (struct window *,
1176 enum glyph_row_area,
1177 int, int, int, int);
1178 static int normal_char_height (struct font *, int);
1179 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1180
1181 static void append_stretch_glyph (struct it *, Lisp_Object,
1182 int, int, int);
1183
1184 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1185 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1186 struct font *, int, bool);
1187 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1188 struct glyph_row *,
1189 struct window *, struct face *,
1190 struct face *);
1191 static void get_cursor_offset_for_mouse_face (struct window *w,
1192 struct glyph_row *row,
1193 int *offset);
1194 #endif
1195
1196 static void produce_special_glyphs (struct it *, enum display_element_type);
1197 static void pad_mode_line (struct it *, bool);
1198 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1199 static bool coords_in_mouse_face_p (struct window *, int, int);
1200 static void reset_box_start_end_flags (struct it *);
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214 int
1215 window_text_bottom_y (struct window *w)
1216 {
1217 int height = WINDOW_PIXEL_HEIGHT (w);
1218
1219 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1220
1221 if (window_wants_mode_line (w))
1222 height -= CURRENT_MODE_LINE_HEIGHT (w);
1223
1224 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1225
1226 return height;
1227 }
1228
1229
1230
1231
1232
1233 int
1234 window_box_width (struct window *w, enum glyph_row_area area)
1235 {
1236 int width = w->pixel_width;
1237
1238 if (!w->pseudo_window_p)
1239 {
1240 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1241 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1242
1243 if (area == TEXT_AREA)
1244 width -= (WINDOW_MARGINS_WIDTH (w)
1245 + WINDOW_FRINGES_WIDTH (w));
1246 else if (area == LEFT_MARGIN_AREA)
1247 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1248 else if (area == RIGHT_MARGIN_AREA)
1249 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1250 }
1251
1252
1253
1254 return max (0, width);
1255 }
1256
1257
1258
1259
1260
1261 int
1262 window_box_height (struct window *w)
1263 {
1264 struct frame *f = XFRAME (w->frame);
1265 int height = WINDOW_PIXEL_HEIGHT (w);
1266
1267 eassert (height >= 0);
1268
1269 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1270 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1271
1272
1273
1274
1275
1276
1277
1278 if (window_wants_mode_line (w))
1279 {
1280 if (w->mode_line_height >= 0)
1281 height -= w->mode_line_height;
1282 else
1283 {
1284 struct glyph_row *ml_row
1285 = (w->current_matrix && w->current_matrix->rows
1286 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1287 : 0);
1288 if (ml_row && ml_row->mode_line_p)
1289 height -= ml_row->height;
1290 else
1291 height -= estimate_mode_line_height
1292 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1293 }
1294 }
1295
1296 if (window_wants_tab_line (w))
1297 {
1298 if (w->tab_line_height >= 0)
1299 height -= w->tab_line_height;
1300 else
1301 {
1302 struct glyph_row *tl_row
1303 = (w->current_matrix && w->current_matrix->rows
1304 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1305 : 0);
1306 if (tl_row && tl_row->mode_line_p)
1307 height -= tl_row->height;
1308 else
1309 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1310 }
1311 }
1312
1313 if (window_wants_header_line (w))
1314 {
1315 if (w->header_line_height >= 0)
1316 height -= w->header_line_height;
1317 else
1318 {
1319 struct glyph_row *hl_row
1320 = (w->current_matrix && w->current_matrix->rows
1321 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1322 : 0);
1323 if (hl_row && hl_row->mode_line_p)
1324 height -= hl_row->height;
1325 else
1326 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1327 }
1328 }
1329
1330
1331
1332 return max (0, height);
1333 }
1334
1335
1336
1337
1338
1339 int
1340 window_box_left_offset (struct window *w, enum glyph_row_area area)
1341 {
1342 int x;
1343
1344 if (w->pseudo_window_p)
1345 return 0;
1346
1347 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1348
1349 if (area == TEXT_AREA)
1350 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1351 + window_box_width (w, LEFT_MARGIN_AREA));
1352 else if (area == RIGHT_MARGIN_AREA)
1353 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1354 + window_box_width (w, LEFT_MARGIN_AREA)
1355 + window_box_width (w, TEXT_AREA)
1356 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1357 ? 0
1358 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1359 else if (area == LEFT_MARGIN_AREA
1360 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1361 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1362
1363
1364 return min (x, w->pixel_width);
1365 }
1366
1367
1368
1369
1370
1371
1372 static int
1373 window_box_right_offset (struct window *w, enum glyph_row_area area)
1374 {
1375
1376 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1377 w->pixel_width);
1378 }
1379
1380
1381
1382
1383
1384 int
1385 window_box_left (struct window *w, enum glyph_row_area area)
1386 {
1387 struct frame *f = XFRAME (w->frame);
1388 int x;
1389
1390 if (w->pseudo_window_p)
1391 return FRAME_INTERNAL_BORDER_WIDTH (f);
1392
1393 x = (WINDOW_LEFT_EDGE_X (w)
1394 + window_box_left_offset (w, area));
1395
1396 return x;
1397 }
1398
1399
1400
1401
1402
1403
1404 int
1405 window_box_right (struct window *w, enum glyph_row_area area)
1406 {
1407 return window_box_left (w, area) + window_box_width (w, area);
1408 }
1409
1410
1411
1412
1413
1414
1415
1416
1417 void
1418 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1419 int *box_y, int *box_width, int *box_height)
1420 {
1421 if (box_width)
1422 *box_width = window_box_width (w, area);
1423 if (box_height)
1424 *box_height = window_box_height (w);
1425 if (box_x)
1426 *box_x = window_box_left (w, area);
1427 if (box_y)
1428 {
1429 *box_y = WINDOW_TOP_EDGE_Y (w);
1430 if (window_wants_tab_line (w))
1431 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1432 if (window_wants_header_line (w))
1433 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1434 }
1435 }
1436
1437 #ifdef HAVE_WINDOW_SYSTEM
1438
1439
1440
1441
1442
1443
1444
1445
1446 static void
1447 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1448 int *bottom_right_x, int *bottom_right_y)
1449 {
1450 window_box (w, ANY_AREA, top_left_x, top_left_y,
1451 bottom_right_x, bottom_right_y);
1452 *bottom_right_x += *top_left_x;
1453 *bottom_right_y += *top_left_y;
1454 }
1455
1456 #endif
1457
1458
1459
1460
1461
1462
1463
1464
1465 int
1466 line_bottom_y (struct it *it)
1467 {
1468 int line_height = it->max_ascent + it->max_descent;
1469 int line_top_y = it->current_y;
1470
1471 if (line_height == 0)
1472 {
1473 if (last_height)
1474 line_height = last_height;
1475 else if (IT_CHARPOS (*it) < ZV)
1476 {
1477 move_it_by_lines (it, 1);
1478 line_height = (it->max_ascent || it->max_descent
1479 ? it->max_ascent + it->max_descent
1480 : last_height);
1481 }
1482 else
1483 {
1484 struct glyph_row *row = it->glyph_row;
1485
1486
1487 it->glyph_row = NULL;
1488 it->what = IT_CHARACTER;
1489 it->c = ' ';
1490 it->len = 1;
1491 PRODUCE_GLYPHS (it);
1492 line_height = it->ascent + it->descent;
1493 it->glyph_row = row;
1494 }
1495 }
1496
1497 return line_top_y + line_height;
1498 }
1499
1500 DEFUN ("line-pixel-height", Fline_pixel_height,
1501 Sline_pixel_height, 0, 0, 0,
1502 doc:
1503
1504 )
1505 (void)
1506 {
1507 struct it it;
1508 struct text_pos pt;
1509 struct window *w = XWINDOW (selected_window);
1510 struct buffer *old_buffer = NULL;
1511 Lisp_Object result;
1512
1513 if (XBUFFER (w->contents) != current_buffer)
1514 {
1515 old_buffer = current_buffer;
1516 set_buffer_internal_1 (XBUFFER (w->contents));
1517 }
1518 SET_TEXT_POS (pt, PT, PT_BYTE);
1519 void *itdata = bidi_shelve_cache ();
1520 start_display (&it, w, pt);
1521
1522
1523
1524 move_it_by_lines (&it, 0);
1525 it.vpos = it.current_y = 0;
1526 last_height = 0;
1527 result = make_fixnum (line_bottom_y (&it));
1528 if (old_buffer)
1529 set_buffer_internal_1 (old_buffer);
1530
1531 bidi_unshelve_cache (itdata, false);
1532 return result;
1533 }
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549 int
1550 default_line_pixel_height (struct window *w)
1551 {
1552 struct frame *f = WINDOW_XFRAME (w);
1553 int height = FRAME_LINE_HEIGHT (f);
1554
1555 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1556 {
1557 struct buffer *b = XBUFFER (w->contents);
1558 Lisp_Object val = BVAR (b, extra_line_spacing);
1559
1560 if (NILP (val))
1561 val = BVAR (&buffer_defaults, extra_line_spacing);
1562 if (!NILP (val))
1563 {
1564 if (RANGED_FIXNUMP (0, val, INT_MAX))
1565 height += XFIXNAT (val);
1566 else if (FLOATP (val))
1567 {
1568 int addon = XFLOAT_DATA (val) * height + 0.5;
1569
1570 if (addon >= 0)
1571 height += addon;
1572 }
1573 }
1574 else
1575 height += f->extra_line_spacing;
1576 }
1577
1578 return height;
1579 }
1580
1581
1582
1583 static Lisp_Object
1584 string_from_display_spec (Lisp_Object spec)
1585 {
1586 if (VECTORP (spec))
1587 {
1588 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1589 if (STRINGP (AREF (spec, i)))
1590 return AREF (spec, i);
1591 }
1592 else
1593 {
1594 for (; CONSP (spec); spec = XCDR (spec))
1595 if (STRINGP (XCAR (spec)))
1596 return XCAR (spec);
1597 }
1598 return spec;
1599 }
1600
1601
1602
1603
1604
1605 static int
1606 window_hscroll_limited (struct window *w, struct frame *f)
1607 {
1608 ptrdiff_t window_hscroll = w->hscroll;
1609 int window_text_width = window_box_width (w, TEXT_AREA);
1610 int colwidth = FRAME_COLUMN_WIDTH (f);
1611
1612 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1613 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1614
1615 return window_hscroll;
1616 }
1617
1618
1619
1620
1621
1622 static void
1623 reset_box_start_end_flags (struct it *it)
1624 {
1625
1626
1627 if (it->area == TEXT_AREA
1628
1629 && !(it->what == IT_IMAGE && it->image_id < 0))
1630 {
1631
1632
1633
1634
1635 if (it->face_box_p)
1636 it->start_of_box_run_p = false;
1637 it->end_of_box_run_p = false;
1638 }
1639 }
1640
1641
1642
1643
1644
1645
1646
1647 bool
1648 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1649 int *rtop, int *rbot, int *rowh, int *vpos)
1650 {
1651 struct it it;
1652 void *itdata = bidi_shelve_cache ();
1653 struct text_pos top;
1654 bool visible_p = false;
1655 struct buffer *old_buffer = NULL;
1656 bool r2l = false;
1657
1658 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1659 return visible_p;
1660
1661 if (XBUFFER (w->contents) != current_buffer)
1662 {
1663 old_buffer = current_buffer;
1664 set_buffer_internal_1 (XBUFFER (w->contents));
1665 }
1666
1667 SET_TEXT_POS_FROM_MARKER (top, w->start);
1668
1669
1670
1671
1672 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1673 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1674
1675
1676
1677 if (charpos >= 0 && CHARPOS (top) > charpos)
1678 return visible_p;
1679
1680
1681
1682
1683
1684
1685
1686
1687 int prev_mode_line_height = w->mode_line_height;
1688 int prev_header_line_height = w->header_line_height;
1689 int prev_tab_line_height = w->tab_line_height;
1690
1691 if (window_wants_mode_line (w))
1692 {
1693 Lisp_Object window_mode_line_format
1694 = window_parameter (w, Qmode_line_format);
1695
1696 w->mode_line_height
1697 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1698 NILP (window_mode_line_format)
1699 ? BVAR (current_buffer, mode_line_format)
1700 : window_mode_line_format);
1701 }
1702
1703 if (window_wants_tab_line (w))
1704 {
1705 Lisp_Object window_tab_line_format
1706 = window_parameter (w, Qtab_line_format);
1707
1708 w->tab_line_height
1709 = display_mode_line (w, TAB_LINE_FACE_ID,
1710 NILP (window_tab_line_format)
1711 ? BVAR (current_buffer, tab_line_format)
1712 : window_tab_line_format);
1713 }
1714
1715 if (window_wants_header_line (w))
1716 {
1717 Lisp_Object window_header_line_format
1718 = window_parameter (w, Qheader_line_format);
1719
1720 w->header_line_height
1721 = display_mode_line (w, HEADER_LINE_FACE_ID,
1722 NILP (window_header_line_format)
1723 ? BVAR (current_buffer, header_line_format)
1724 : window_header_line_format);
1725 }
1726
1727 start_display (&it, w, top);
1728 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1729 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1730
1731
1732
1733 if (!NILP (Vdisplay_line_numbers)
1734 && it.current_x >= it.first_visible_x
1735 && IT_CHARPOS (it) == charpos
1736 && !it.line_number_produced_p)
1737 {
1738
1739
1740
1741 if (!it.lnum_pixel_width)
1742 {
1743 struct it it2;
1744 void *it2data = NULL;
1745
1746 SAVE_IT (it2, it, it2data);
1747 move_it_by_lines (&it, 1);
1748 it2.lnum_pixel_width = it.lnum_pixel_width;
1749 RESTORE_IT (&it, &it2, it2data);
1750 }
1751 it.current_x += it.lnum_pixel_width;
1752 }
1753
1754 if (charpos >= 0
1755 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1756 && IT_CHARPOS (it) >= charpos)
1757
1758
1759
1760 || (it.bidi_p && it.bidi_it.scan_dir == -1
1761 && IT_CHARPOS (it) <= charpos)))
1762 {
1763
1764
1765
1766
1767
1768
1769 int top_x = it.current_x;
1770 int top_y = it.current_y;
1771 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1772 int bottom_y;
1773 struct it save_it;
1774 void *save_it_data = NULL;
1775
1776
1777 SAVE_IT (save_it, it, save_it_data);
1778 last_height = 0;
1779 bottom_y = line_bottom_y (&it);
1780 if (top_y < window_top_y)
1781 visible_p = bottom_y > window_top_y;
1782 else if (top_y < it.last_visible_y)
1783 visible_p = true;
1784 if (bottom_y >= it.last_visible_y
1785 && it.bidi_p && it.bidi_it.scan_dir == -1
1786 && IT_CHARPOS (it) < charpos)
1787 {
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798 int ten_more_lines = 10 * default_line_pixel_height (w);
1799
1800 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1801 MOVE_TO_POS | MOVE_TO_Y);
1802 if (it.current_y > top_y)
1803 visible_p = false;
1804
1805 }
1806 RESTORE_IT (&it, &save_it, save_it_data);
1807 if (visible_p)
1808 {
1809 if (it.method == GET_FROM_DISPLAY_VECTOR)
1810 {
1811
1812
1813 if (charpos < 2 || top.charpos >= charpos)
1814 top_x = it.glyph_row->x;
1815 else
1816 {
1817 struct it it2, it2_prev;
1818
1819
1820
1821
1822
1823
1824 start_display (&it2, w, top);
1825 it2.glyph_row = NULL;
1826 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1827
1828
1829
1830
1831 if (IT_CHARPOS (it2) != charpos - 1)
1832 it2_prev = it2;
1833 else
1834 {
1835
1836
1837
1838 do {
1839 get_next_display_element (&it2);
1840 PRODUCE_GLYPHS (&it2);
1841 it2_prev = it2;
1842 set_iterator_to_next (&it2, true);
1843 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1844 && IT_CHARPOS (it2) < charpos);
1845 }
1846 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1847 || it2_prev.current_x > it2_prev.last_visible_x)
1848 top_x = it.glyph_row->x;
1849 else
1850 {
1851 top_x = it2_prev.current_x;
1852 top_y = it2_prev.current_y;
1853 }
1854 }
1855 }
1856 else if (IT_CHARPOS (it) != charpos)
1857 {
1858 Lisp_Object cpos = make_fixnum (charpos);
1859 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1860 Lisp_Object string = string_from_display_spec (spec);
1861 struct text_pos tpos;
1862 bool newline_in_string
1863 = (STRINGP (string)
1864 && memchr (SDATA (string), '\n', SBYTES (string)));
1865
1866 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1867 bool replacing_spec_p
1868 = (!NILP (spec)
1869 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1870 charpos, FRAME_WINDOW_P (it.f)));
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887 if (replacing_spec_p)
1888 {
1889 Lisp_Object startpos, endpos;
1890 EMACS_INT start, end;
1891 struct it it3;
1892
1893
1894
1895 endpos =
1896 Fnext_single_char_property_change (cpos, Qdisplay,
1897 Qnil, Qnil);
1898 startpos =
1899 Fprevious_single_char_property_change (endpos, Qdisplay,
1900 Qnil, Qnil);
1901 start = XFIXNAT (startpos);
1902 end = XFIXNAT (endpos);
1903
1904
1905 start_display (&it3, w, top);
1906 if (start > CHARPOS (top))
1907 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1908
1909
1910
1911
1912 if (it3.method == GET_FROM_BUFFER
1913 && (it3.c == '\n'
1914 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1915 move_it_by_lines (&it3, 1);
1916 else if (move_it_in_display_line_to (&it3, -1,
1917 it3.current_x
1918 + it3.pixel_width,
1919 MOVE_TO_X)
1920 == MOVE_LINE_CONTINUED)
1921 {
1922 move_it_by_lines (&it3, 1);
1923
1924
1925
1926 if (it3.line_wrap == WORD_WRAP)
1927 move_it_by_lines (&it3, -1);
1928 }
1929
1930
1931
1932 top_y = it3.current_y;
1933 if (it3.bidi_p)
1934 {
1935
1936
1937
1938
1939
1940 start_display (&it3, w, top);
1941 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1942 if (it3.current_y < top_y)
1943 top_y = it3.current_y;
1944 }
1945
1946
1947
1948 start_display (&it3, w, top);
1949 it3.glyph_row = NULL;
1950 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1951
1952
1953
1954
1955
1956
1957
1958 bool it3_moved = false;
1959 int top_x_before_string = it3.current_x;
1960
1961
1962
1963
1964
1965 while (get_next_display_element (&it3))
1966 {
1967 if (!EQ (it3.object, string))
1968 top_x_before_string = it3.current_x;
1969 PRODUCE_GLYPHS (&it3);
1970 if ((it3.bidi_it.scan_dir == 1
1971 && IT_CHARPOS (it3) >= charpos)
1972 || (it3.bidi_it.scan_dir == -1
1973 && IT_CHARPOS (it3) <= charpos)
1974 || ITERATOR_AT_END_OF_LINE_P (&it3))
1975 break;
1976 it3_moved = true;
1977 set_iterator_to_next (&it3, false);
1978 }
1979 top_x = it3.current_x - it3.pixel_width;
1980
1981
1982
1983 if (!it3.line_number_produced_p)
1984 {
1985 if (it3.lnum_pixel_width > 0)
1986 {
1987 top_x += it3.lnum_pixel_width;
1988 top_x_before_string += it3.lnum_pixel_width;
1989 }
1990 else if (it.line_number_produced_p)
1991 {
1992 top_x += it.lnum_pixel_width;
1993 top_x_before_string += it3.lnum_pixel_width;
1994 }
1995 }
1996
1997
1998
1999
2000
2001
2002 if (it3_moved
2003 && newline_in_string
2004 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2005 top_x = top_x_before_string;
2006 }
2007 }
2008
2009 *x = top_x;
2010
2011
2012
2013
2014 if (it.ascent == 0 && it.what == IT_IMAGE
2015 && it.method != GET_FROM_IMAGE
2016 && it.image_id < 0
2017 && it.max_ascent > 0)
2018 *y = max (top_y, window_top_y);
2019 else
2020 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2021 *rtop = max (0, window_top_y - top_y);
2022 *rbot = max (0, bottom_y - it.last_visible_y);
2023 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2024 - max (top_y, window_top_y)));
2025 *vpos = it.vpos;
2026 if (it.bidi_it.paragraph_dir == R2L)
2027 r2l = true;
2028 }
2029 }
2030 else
2031 {
2032
2033
2034
2035 struct it it2;
2036 void *it2data = NULL;
2037
2038 SAVE_IT (it2, it, it2data);
2039 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2040 move_it_by_lines (&it, 1);
2041 if (charpos < IT_CHARPOS (it)
2042 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2043 {
2044 visible_p = true;
2045 RESTORE_IT (&it2, &it2, it2data);
2046 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2047 *x = it2.current_x;
2048 if (it2.ascent == 0 && it2.what == IT_IMAGE
2049 && it2.method != GET_FROM_IMAGE
2050 && it2.image_id < 0
2051 && it2.max_ascent > 0)
2052 *y = it2.current_y;
2053 else
2054 *y = it2.current_y + it2.max_ascent - it2.ascent;
2055 *rtop = max (0, -it2.current_y);
2056 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2057 - it.last_visible_y));
2058 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2059 it.last_visible_y)
2060 - max (max (it2.current_y,
2061 WINDOW_TAB_LINE_HEIGHT (w)),
2062 WINDOW_HEADER_LINE_HEIGHT (w))));
2063 *vpos = it2.vpos;
2064 if (it2.bidi_it.paragraph_dir == R2L)
2065 r2l = true;
2066 }
2067 else
2068 bidi_unshelve_cache (it2data, true);
2069 }
2070 bidi_unshelve_cache (itdata, false);
2071
2072 if (old_buffer)
2073 set_buffer_internal_1 (old_buffer);
2074
2075 if (visible_p)
2076 {
2077 if (w->hscroll > 0)
2078 *x -=
2079 window_hscroll_limited (w, WINDOW_XFRAME (w))
2080 * WINDOW_FRAME_COLUMN_WIDTH (w);
2081
2082
2083
2084
2085
2086 if (r2l)
2087 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2088 }
2089
2090 #if false
2091
2092 if (visible_p)
2093 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2094 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2095 else
2096 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2097 #endif
2098
2099
2100 w->mode_line_height = prev_mode_line_height;
2101 w->header_line_height = prev_header_line_height;
2102 w->tab_line_height = prev_tab_line_height;
2103
2104 return visible_p;
2105 }
2106
2107
2108
2109
2110
2111
2112
2113 static int
2114 check_char_and_length (const unsigned char *str, int *len)
2115 {
2116 int c = string_char_and_length (str, len);
2117 if (!CHAR_VALID_P (c))
2118
2119
2120
2121 c = '?';
2122
2123 return c;
2124 }
2125
2126
2127
2128
2129
2130
2131 static struct text_pos
2132 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2133 {
2134 eassert (STRINGP (string) && nchars >= 0);
2135
2136 if (STRING_MULTIBYTE (string))
2137 {
2138 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2139
2140 while (nchars--)
2141 {
2142 int len = BYTES_BY_CHAR_HEAD (*p);
2143 p += len;
2144 CHARPOS (pos) += 1;
2145 BYTEPOS (pos) += len;
2146 }
2147 }
2148 else
2149 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2150
2151 return pos;
2152 }
2153
2154
2155
2156
2157
2158 static struct text_pos
2159 string_pos (ptrdiff_t charpos, Lisp_Object string)
2160 {
2161 struct text_pos pos;
2162 eassert (STRINGP (string));
2163 eassert (charpos >= 0);
2164 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2165 return pos;
2166 }
2167
2168
2169
2170
2171
2172
2173 static struct text_pos
2174 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2175 {
2176 struct text_pos pos;
2177
2178 eassert (s != NULL);
2179 eassert (charpos >= 0);
2180
2181 if (multibyte_p)
2182 {
2183 SET_TEXT_POS (pos, 0, 0);
2184 while (charpos--)
2185 {
2186 int len = BYTES_BY_CHAR_HEAD (*s);
2187 s += len;
2188 CHARPOS (pos) += 1;
2189 BYTEPOS (pos) += len;
2190 }
2191 }
2192 else
2193 SET_TEXT_POS (pos, charpos, charpos);
2194
2195 return pos;
2196 }
2197
2198
2199
2200
2201
2202 static ptrdiff_t
2203 number_of_chars (const char *s, bool multibyte_p)
2204 {
2205 ptrdiff_t nchars;
2206
2207 if (multibyte_p)
2208 {
2209 ptrdiff_t rest = strlen (s);
2210 const unsigned char *p = (const unsigned char *) s;
2211
2212 for (nchars = 0; rest > 0; ++nchars)
2213 {
2214 int len = BYTES_BY_CHAR_HEAD (*p);
2215 rest -= len, p += len;
2216 }
2217 }
2218 else
2219 nchars = strlen (s);
2220
2221 return nchars;
2222 }
2223
2224
2225
2226
2227
2228
2229 static void
2230 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2231 {
2232 eassert (STRINGP (string));
2233 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2234
2235 if (STRING_MULTIBYTE (string))
2236 *newpos = string_pos_nchars_ahead (pos, string,
2237 CHARPOS (*newpos) - CHARPOS (pos));
2238 else
2239 BYTEPOS (*newpos) = CHARPOS (*newpos);
2240 }
2241
2242
2243
2244
2245
2246 int
2247 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2248 {
2249 #ifdef HAVE_WINDOW_SYSTEM
2250 if (FRAME_WINDOW_P (f))
2251 {
2252 int height = FONT_HEIGHT (FRAME_FONT (f));
2253
2254
2255
2256 if (FRAME_FACE_CACHE (f))
2257 {
2258 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2259 if (face)
2260 {
2261 if (face->font)
2262 height = normal_char_height (face->font, -1);
2263 if (face->box_horizontal_line_width > 0)
2264 height += 2 * face->box_horizontal_line_width;
2265 }
2266 }
2267
2268 return height;
2269 }
2270 #endif
2271
2272 return 1;
2273 }
2274
2275
2276
2277
2278
2279
2280 void
2281 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2282 NativeRectangle *bounds, bool noclip)
2283 {
2284
2285 #ifdef HAVE_WINDOW_SYSTEM
2286 if (FRAME_WINDOW_P (f))
2287 {
2288
2289
2290 if (pix_x < 0)
2291 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2292 if (pix_y < 0)
2293 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2294
2295 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2296 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2297
2298 if (bounds)
2299 STORE_NATIVE_RECT (*bounds,
2300 FRAME_COL_TO_PIXEL_X (f, pix_x),
2301 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2302 FRAME_COLUMN_WIDTH (f) - 1,
2303 FRAME_LINE_HEIGHT (f) - 1);
2304
2305
2306 if (!noclip)
2307 {
2308 if (pix_x < 0)
2309 pix_x = 0;
2310 else if (pix_x > FRAME_TOTAL_COLS (f))
2311 pix_x = FRAME_TOTAL_COLS (f);
2312
2313 if (pix_y < 0)
2314 pix_y = 0;
2315 else if (pix_y > FRAME_TOTAL_LINES (f))
2316 pix_y = FRAME_TOTAL_LINES (f);
2317 }
2318 }
2319 #endif
2320
2321 *x = pix_x;
2322 *y = pix_y;
2323 }
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334 struct glyph *
2335 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2336 int *dx, int *dy, int *area)
2337 {
2338 struct glyph *glyph, *end;
2339 struct glyph_row *row = NULL;
2340 int x0, i;
2341
2342
2343 for (i = 0; i < w->current_matrix->nrows; ++i)
2344 {
2345 row = MATRIX_ROW (w->current_matrix, i);
2346 if (!row->enabled_p)
2347 return NULL;
2348 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2349 break;
2350 }
2351
2352 *vpos = i;
2353 *hpos = 0;
2354
2355
2356 if (i == w->current_matrix->nrows)
2357 return NULL;
2358
2359
2360 if (w->pseudo_window_p)
2361 {
2362 *area = TEXT_AREA;
2363 x0 = 0;
2364 }
2365 else
2366 {
2367 if (x < window_box_left_offset (w, TEXT_AREA))
2368 {
2369 *area = LEFT_MARGIN_AREA;
2370 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2371 }
2372 else if (x < window_box_right_offset (w, TEXT_AREA))
2373 {
2374 *area = TEXT_AREA;
2375 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2376 }
2377 else
2378 {
2379 *area = RIGHT_MARGIN_AREA;
2380 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2381 }
2382 }
2383
2384
2385 glyph = row->glyphs[*area];
2386 end = glyph + row->used[*area];
2387 x -= x0;
2388 while (glyph < end && x >= glyph->pixel_width)
2389 {
2390 x -= glyph->pixel_width;
2391 ++glyph;
2392 }
2393
2394 if (glyph == end)
2395 return NULL;
2396
2397 if (dx)
2398 {
2399 *dx = x;
2400 *dy = y - (row->y + row->ascent - glyph->ascent);
2401 }
2402
2403 *hpos = glyph - row->glyphs[*area];
2404 return glyph;
2405 }
2406
2407
2408
2409
2410 static void
2411 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2412 {
2413 if (w->pseudo_window_p)
2414 {
2415
2416
2417 struct frame *f = XFRAME (w->frame);
2418 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2419 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2420 }
2421 else
2422 {
2423 *x -= WINDOW_LEFT_EDGE_X (w);
2424 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2425 }
2426 }
2427
2428 #ifdef HAVE_WINDOW_SYSTEM
2429
2430
2431
2432
2433
2434 int
2435 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2436 {
2437 Emacs_Rectangle r;
2438
2439 if (n <= 0)
2440 return 0;
2441
2442 if (s->row->full_width_p)
2443 {
2444
2445 r.x = WINDOW_LEFT_EDGE_X (s->w);
2446 if (s->row->mode_line_p)
2447 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2448 else
2449 r.width = WINDOW_PIXEL_WIDTH (s->w);
2450
2451
2452
2453 if (s->w->pseudo_window_p)
2454 r.height = s->row->visible_height;
2455 else
2456 r.height = s->height;
2457 }
2458 else
2459 {
2460
2461 r.x = window_box_left (s->w, s->area);
2462 r.width = window_box_width (s->w, s->area);
2463 r.height = s->row->visible_height;
2464 }
2465
2466 if (s->clip_head)
2467 if (r.x < s->clip_head->x)
2468 {
2469 if (r.width >= s->clip_head->x - r.x)
2470 r.width -= s->clip_head->x - r.x;
2471 else
2472 r.width = 0;
2473 r.x = s->clip_head->x;
2474 }
2475 if (s->clip_tail)
2476 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2477 {
2478 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2479 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2480 else
2481 r.width = 0;
2482 }
2483
2484
2485
2486
2487 if (s->for_overlaps)
2488 {
2489 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2490 r.height = window_text_bottom_y (s->w) - r.y;
2491
2492
2493
2494
2495
2496
2497 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2498 {
2499 Emacs_Rectangle rc, r_save = r;
2500
2501 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2502 rc.y = s->w->phys_cursor.y;
2503 rc.width = s->w->phys_cursor_width;
2504 rc.height = s->w->phys_cursor_height;
2505
2506 gui_intersect_rectangles (&r_save, &rc, &r);
2507 }
2508 }
2509 else
2510 {
2511
2512
2513
2514 if (!s->row->full_width_p
2515 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2516 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2517 else
2518 r.y = max (0, s->row->y);
2519 }
2520
2521 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2522
2523
2524
2525 if (s->hl == DRAW_CURSOR)
2526 {
2527 struct glyph *glyph = s->first_glyph;
2528 int height, max_y;
2529
2530 if (s->x > r.x)
2531 {
2532 if (r.width >= s->x - r.x)
2533 r.width -= s->x - r.x;
2534 else
2535 r.width = 0;
2536 r.x = s->x;
2537 }
2538 r.width = min (r.width, glyph->pixel_width);
2539
2540
2541 height = min (glyph->ascent + glyph->descent,
2542 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2543 max_y = window_text_bottom_y (s->w) - height;
2544 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2545 if (s->ybase - glyph->ascent > max_y)
2546 {
2547 r.y = max_y;
2548 r.height = height;
2549 }
2550 else
2551 {
2552
2553 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2554 if (height < r.height)
2555 {
2556 max_y = r.y + r.height;
2557 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2558 r.height = min (max_y - r.y, height);
2559 }
2560 }
2561 }
2562
2563 if (s->row->clip)
2564 {
2565 Emacs_Rectangle r_save = r;
2566
2567 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2568 r.width = 0;
2569 }
2570
2571 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2572 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2573 {
2574 #ifdef CONVERT_FROM_EMACS_RECT
2575 CONVERT_FROM_EMACS_RECT (r, *rects);
2576 #else
2577 *rects = r;
2578 #endif
2579 return 1;
2580 }
2581 else
2582 {
2583
2584
2585
2586
2587 #ifdef CONVERT_FROM_EMACS_RECT
2588 Emacs_Rectangle rs[2];
2589 #else
2590 Emacs_Rectangle *rs = rects;
2591 #endif
2592 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2593
2594 if (s->for_overlaps & OVERLAPS_PRED)
2595 {
2596 rs[i] = r;
2597 if (r.y + r.height > row_y)
2598 {
2599 if (r.y < row_y)
2600 rs[i].height = row_y - r.y;
2601 else
2602 rs[i].height = 0;
2603 }
2604 i++;
2605 }
2606 if (s->for_overlaps & OVERLAPS_SUCC)
2607 {
2608 rs[i] = r;
2609 if (r.y < row_y + s->row->visible_height)
2610 {
2611 if (r.y + r.height > row_y + s->row->visible_height)
2612 {
2613 rs[i].y = row_y + s->row->visible_height;
2614 rs[i].height = r.y + r.height - rs[i].y;
2615 }
2616 else
2617 rs[i].height = 0;
2618 }
2619 i++;
2620 }
2621
2622 n = i;
2623 #ifdef CONVERT_FROM_EMACS_RECT
2624 for (i = 0; i < n; i++)
2625 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2626 #endif
2627 return n;
2628 }
2629 }
2630
2631
2632
2633
2634 void
2635 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2636 {
2637 get_glyph_string_clip_rects (s, nr, 1);
2638 }
2639
2640
2641
2642
2643
2644
2645
2646 void
2647 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2648 struct glyph *glyph, int *xp, int *yp, int *heightp)
2649 {
2650 struct frame *f = XFRAME (WINDOW_FRAME (w));
2651 int x, y, wd, h, h0, y0, ascent;
2652
2653
2654
2655
2656
2657 wd = glyph->pixel_width;
2658
2659 x = w->phys_cursor.x;
2660 if (x < 0)
2661 {
2662 wd += x;
2663 x = 0;
2664 }
2665
2666 if (glyph->type == STRETCH_GLYPH
2667 && !x_stretch_cursor_p)
2668 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2669 w->phys_cursor_width = wd;
2670
2671
2672
2673 y = w->phys_cursor.y;
2674 ascent = row->ascent;
2675
2676
2677
2678 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2679 {
2680 y -= glyph->ascent - row->ascent;
2681 ascent = glyph->ascent;
2682 }
2683
2684
2685 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2686
2687 h = max (h0, ascent + glyph->descent);
2688
2689
2690 h = min (h, row->height);
2691 h0 = min (h0, ascent + glyph->descent);
2692
2693 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2694 if (y < y0)
2695 {
2696 h = max (h - (y0 - y) + 1, h0);
2697 y = y0 - 1;
2698 }
2699 else
2700 {
2701 y0 = window_text_bottom_y (w) - h0;
2702 if (y > y0)
2703 {
2704 h += y - y0;
2705 y = y0;
2706 }
2707 }
2708
2709 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2710 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2711 *heightp = h;
2712 }
2713
2714
2715
2716
2717
2718 void
2719 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2720 {
2721 Lisp_Object window;
2722 struct window *w;
2723 struct glyph_row *r, *gr, *end_row;
2724 enum window_part part;
2725 enum glyph_row_area area;
2726 int x, y, width, height;
2727
2728 if (mouse_fine_grained_tracking)
2729 {
2730 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2731 return;
2732 }
2733
2734
2735
2736
2737 if (window_resize_pixelwise)
2738 {
2739 width = height = 1;
2740 goto virtual_glyph;
2741 }
2742 else if (!f->glyphs_initialized_p
2743 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2744 NILP (window)))
2745 {
2746 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2747 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2748 goto virtual_glyph;
2749 }
2750
2751 w = XWINDOW (window);
2752 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2753 height = WINDOW_FRAME_LINE_HEIGHT (w);
2754
2755 x = window_relative_x_coord (w, part, gx);
2756 y = gy - WINDOW_TOP_EDGE_Y (w);
2757
2758 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2759 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2760
2761 if (w->pseudo_window_p)
2762 {
2763 area = TEXT_AREA;
2764 part = ON_MODE_LINE;
2765 goto text_glyph;
2766 }
2767
2768 switch (part)
2769 {
2770 case ON_LEFT_MARGIN:
2771 area = LEFT_MARGIN_AREA;
2772 goto text_glyph;
2773
2774 case ON_RIGHT_MARGIN:
2775 area = RIGHT_MARGIN_AREA;
2776 goto text_glyph;
2777
2778 case ON_TAB_LINE:
2779 case ON_HEADER_LINE:
2780 case ON_MODE_LINE:
2781 gr = (part == ON_TAB_LINE
2782 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2783 : (part == ON_HEADER_LINE
2784 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2785 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2786 gy = gr->y;
2787 area = TEXT_AREA;
2788 goto text_glyph_row_found;
2789
2790 case ON_TEXT:
2791 area = TEXT_AREA;
2792
2793 text_glyph:
2794 gr = 0; gy = 0;
2795 for (; r <= end_row && r->enabled_p; ++r)
2796 if (r->y + r->height > y)
2797 {
2798 gr = r; gy = r->y;
2799 break;
2800 }
2801
2802 text_glyph_row_found:
2803 if (gr && gy <= y)
2804 {
2805 struct glyph *g = gr->glyphs[area];
2806 struct glyph *end = g + gr->used[area];
2807
2808 height = gr->height;
2809 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2810 if (gx + g->pixel_width > x)
2811 break;
2812
2813 if (g < end)
2814 {
2815 if (g->type == IMAGE_GLYPH)
2816 {
2817
2818
2819 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2820 return;
2821 }
2822 width = g->pixel_width;
2823 }
2824 else
2825 {
2826
2827 x -= gx;
2828 gx += (x / width) * width;
2829 }
2830
2831 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2832 && part != ON_TAB_LINE)
2833 {
2834 gx += window_box_left_offset (w, area);
2835
2836
2837 height = min (height,
2838 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2839 }
2840 }
2841 else
2842 {
2843
2844 gx = (x / width) * width;
2845 y -= gy;
2846 gy += (y / height) * height;
2847 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2848 && part != ON_TAB_LINE)
2849
2850 height = min (height,
2851 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2852 }
2853 break;
2854
2855 case ON_LEFT_FRINGE:
2856 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2857 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2858 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2859 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2860 goto row_glyph;
2861
2862 case ON_RIGHT_FRINGE:
2863 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2864 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2865 : window_box_right_offset (w, TEXT_AREA));
2866 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2867 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2868 && !WINDOW_RIGHTMOST_P (w))
2869 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2870
2871
2872 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2873 else
2874 width = WINDOW_PIXEL_WIDTH (w) - gx;
2875 else
2876 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2877
2878 goto row_glyph;
2879
2880 case ON_VERTICAL_BORDER:
2881 gx = WINDOW_PIXEL_WIDTH (w) - width;
2882 goto row_glyph;
2883
2884 case ON_VERTICAL_SCROLL_BAR:
2885 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2886 ? 0
2887 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2888 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2889 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2890 : 0)));
2891 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2892
2893 row_glyph:
2894 gr = 0, gy = 0;
2895 for (; r <= end_row && r->enabled_p; ++r)
2896 if (r->y + r->height > y)
2897 {
2898 gr = r; gy = r->y;
2899 break;
2900 }
2901
2902 if (gr && gy <= y)
2903 height = gr->height;
2904 else
2905 {
2906
2907 y -= gy;
2908 gy += (y / height) * height;
2909 }
2910 break;
2911
2912 case ON_RIGHT_DIVIDER:
2913 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2914 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2915 gy = 0;
2916
2917 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2918 goto add_edge;
2919
2920 case ON_BOTTOM_DIVIDER:
2921 gx = 0;
2922 width = WINDOW_PIXEL_WIDTH (w);
2923 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2924 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2925 goto add_edge;
2926
2927 default:
2928 ;
2929 virtual_glyph:
2930
2931
2932
2933
2934
2935
2936 if (gx < 0)
2937 gx -= width - 1;
2938 if (gy < 0)
2939 gy -= height - 1;
2940
2941 gx = (gx / width) * width;
2942 gy = (gy / height) * height;
2943
2944 goto store_rect;
2945 }
2946
2947 add_edge:
2948 gx += WINDOW_LEFT_EDGE_X (w);
2949 gy += WINDOW_TOP_EDGE_Y (w);
2950
2951 store_rect:
2952 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2953
2954
2955 #if false && defined HAVE_X_WINDOWS
2956 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2957 f->output_data.x->normal_gc,
2958 gx, gy, width, height);
2959 #endif
2960 }
2961
2962
2963 #endif
2964
2965 static void
2966 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
2967 {
2968 eassert (w);
2969 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
2970 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
2971 w->window_end_vpos
2972 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
2973 }
2974
2975 static bool
2976 hscrolling_current_line_p (struct window *w)
2977 {
2978 return (!w->suspend_auto_hscroll
2979 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
2980 Qcurrent_line));
2981 }
2982
2983
2984
2985
2986
2987
2988
2989 static Lisp_Object
2990 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
2991 {
2992 add_to_log ("Error during redisplay: %S signaled %S",
2993 Flist (nargs, args), arg);
2994 return Qnil;
2995 }
2996
2997
2998
2999
3000
3001 static Lisp_Object
3002 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3003 {
3004 Lisp_Object val;
3005
3006 if (inhibit_eval_during_redisplay)
3007 val = Qnil;
3008 else
3009 {
3010 ptrdiff_t i;
3011 specpdl_ref count = SPECPDL_INDEX ();
3012 Lisp_Object *args;
3013 USE_SAFE_ALLOCA;
3014 SAFE_ALLOCA_LISP (args, nargs);
3015
3016 args[0] = func;
3017 for (i = 1; i < nargs; i++)
3018 args[i] = va_arg (ap, Lisp_Object);
3019
3020 specbind (Qinhibit_redisplay, Qt);
3021 if (inhibit_quit)
3022 specbind (Qinhibit_quit, Qt);
3023
3024
3025 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3026 safe_eval_handler);
3027 val = SAFE_FREE_UNBIND_TO (count, val);
3028 }
3029
3030 return val;
3031 }
3032
3033 Lisp_Object
3034 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3035 {
3036 Lisp_Object retval;
3037 va_list ap;
3038
3039 va_start (ap, func);
3040 retval = safe__call (false, nargs, func, ap);
3041 va_end (ap);
3042 return retval;
3043 }
3044
3045
3046
3047
3048 Lisp_Object
3049 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3050 {
3051 return safe_call (2, fn, arg);
3052 }
3053
3054 static Lisp_Object
3055 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3056 {
3057 Lisp_Object retval;
3058 va_list ap;
3059
3060 va_start (ap, fn);
3061 retval = safe__call (inhibit_quit, 2, fn, ap);
3062 va_end (ap);
3063 return retval;
3064 }
3065
3066 Lisp_Object
3067 safe_eval (Lisp_Object sexpr)
3068 {
3069 return safe__call1 (false, Qeval, sexpr);
3070 }
3071
3072 static Lisp_Object
3073 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3074 {
3075 return safe__call1 (inhibit_quit, Qeval, sexpr);
3076 }
3077
3078
3079
3080
3081 Lisp_Object
3082 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3083 {
3084 return safe_call (3, fn, arg1, arg2);
3085 }
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096 static void
3097 CHECK_IT (struct it *it)
3098 {
3099 #if false
3100 if (it->method == GET_FROM_STRING)
3101 {
3102 eassert (STRINGP (it->string));
3103 eassert (IT_STRING_CHARPOS (*it) >= 0);
3104 }
3105 else
3106 {
3107 eassert (IT_STRING_CHARPOS (*it) < 0);
3108 if (it->method == GET_FROM_BUFFER)
3109 {
3110
3111 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3112 }
3113 }
3114
3115 if (it->dpvec)
3116 eassert (it->current.dpvec_index >= 0);
3117 else
3118 eassert (it->current.dpvec_index < 0);
3119 #endif
3120 }
3121
3122
3123
3124
3125
3126 static void
3127 CHECK_WINDOW_END (struct window *w)
3128 {
3129 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3130 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3131 {
3132 struct glyph_row *row;
3133 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3134 !row->enabled_p
3135 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3136 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3137 }
3138 #endif
3139 }
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164 void
3165 init_iterator (struct it *it, struct window *w,
3166 ptrdiff_t charpos, ptrdiff_t bytepos,
3167 struct glyph_row *row, enum face_id base_face_id)
3168 {
3169 enum face_id remapped_base_face_id = base_face_id;
3170 int body_width = 0, body_height = 0;
3171
3172
3173 eassert (w != NULL && it != NULL);
3174 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3175 && charpos <= ZV));
3176
3177
3178
3179
3180
3181 if (!inhibit_free_realized_faces)
3182 {
3183 if (face_change)
3184 {
3185 face_change = false;
3186 XFRAME (w->frame)->face_change = 0;
3187 free_all_realized_faces (Qnil);
3188 }
3189 else if (XFRAME (w->frame)->face_change)
3190 {
3191 XFRAME (w->frame)->face_change = 0;
3192 free_all_realized_faces (w->frame);
3193 }
3194 }
3195
3196
3197 if (! NILP (Vface_remapping_alist))
3198 remapped_base_face_id
3199 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3200
3201
3202
3203 if (row == NULL)
3204 {
3205 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3206 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3207 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3208 else if (base_face_id == TAB_LINE_FACE_ID)
3209 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3210 else if (base_face_id == HEADER_LINE_FACE_ID)
3211 {
3212
3213 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3214 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3215 }
3216 }
3217
3218
3219
3220 memclear (it, sizeof *it);
3221 it->current.overlay_string_index = -1;
3222 it->current.dpvec_index = -1;
3223 it->base_face_id = remapped_base_face_id;
3224 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3225 it->paragraph_embedding = L2R;
3226 it->bidi_it.w = w;
3227
3228
3229 XSETWINDOW (it->window, w);
3230 it->w = w;
3231 it->f = XFRAME (w->frame);
3232
3233 it->cmp_it.id = -1;
3234 it->cmp_it.parent_it = it;
3235
3236 if (max_redisplay_ticks > 0)
3237 update_redisplay_ticks (0, w);
3238
3239
3240 if (base_face_id == DEFAULT_FACE_ID
3241 && FRAME_WINDOW_P (it->f))
3242 {
3243 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3244 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3245 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3246 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3247 * FRAME_LINE_HEIGHT (it->f));
3248 else if (it->f->extra_line_spacing > 0)
3249 it->extra_line_spacing = it->f->extra_line_spacing;
3250 }
3251
3252
3253
3254
3255
3256 if (FRAME_FACE_CACHE (it->f) == NULL)
3257 init_frame_faces (it->f);
3258 if (FRAME_FACE_CACHE (it->f)->used == 0)
3259 recompute_basic_faces (it->f);
3260
3261 it->override_ascent = -1;
3262
3263
3264 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3265
3266
3267
3268
3269 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3270 ? (clip_to_bounds
3271 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3272 PTRDIFF_MAX))
3273 : (!NILP (BVAR (current_buffer, selective_display))
3274 ? -1 : 0));
3275 it->selective_display_ellipsis_p
3276 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3277
3278
3279 it->dp = window_display_table (w);
3280
3281
3282 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3283
3284 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3285
3286
3287 if (TRUNCATE != 0)
3288 it->line_wrap = TRUNCATE;
3289 if (base_face_id == DEFAULT_FACE_ID
3290 && !it->w->hscroll
3291 && (WINDOW_FULL_WIDTH_P (it->w)
3292 || NILP (Vtruncate_partial_width_windows)
3293 || (FIXNUMP (Vtruncate_partial_width_windows)
3294
3295 && (XFIXNUM (Vtruncate_partial_width_windows)
3296 <= WINDOW_TOTAL_COLS (it->w))))
3297 && NILP (BVAR (current_buffer, truncate_lines)))
3298 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3299 ? WINDOW_WRAP : WORD_WRAP;
3300
3301
3302
3303
3304
3305
3306
3307 #ifdef HAVE_WINDOW_SYSTEM
3308 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3309 #endif
3310 {
3311 if (it->line_wrap == TRUNCATE)
3312 {
3313
3314 eassert (it->glyph_row == NULL);
3315 produce_special_glyphs (it, IT_TRUNCATION);
3316 it->truncation_pixel_width = it->pixel_width;
3317 }
3318 else
3319 {
3320
3321 eassert (it->glyph_row == NULL);
3322 produce_special_glyphs (it, IT_CONTINUATION);
3323 it->continuation_pixel_width = it->pixel_width;
3324 }
3325 }
3326
3327
3328
3329 it->pixel_width = it->ascent = it->descent = 0;
3330 it->phys_ascent = it->phys_descent = 0;
3331
3332
3333
3334
3335 it->glyph_row = row;
3336 it->area = TEXT_AREA;
3337
3338
3339
3340
3341
3342 if (base_face_id != DEFAULT_FACE_ID)
3343 {
3344
3345 it->first_visible_x = 0;
3346 it->last_visible_x =
3347 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3348 }
3349 else
3350 {
3351
3352
3353
3354
3355
3356
3357 if (hscrolling_current_line_p (w))
3358 {
3359 if (w->min_hscroll > 0)
3360 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3361 else
3362 it->first_visible_x = 0;
3363 }
3364 else
3365 it->first_visible_x =
3366 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3367
3368 body_width = window_box_width (w, TEXT_AREA);
3369 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3370 && body_width != w->old_body_pixel_width)
3371 FRAME_WINDOW_CHANGE (it->f) = true;
3372 it->last_visible_x = it->first_visible_x + body_width;
3373
3374
3375
3376
3377 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3378 {
3379 if (it->line_wrap == TRUNCATE)
3380 it->last_visible_x -= it->truncation_pixel_width;
3381 else
3382 it->last_visible_x -= it->continuation_pixel_width;
3383 }
3384
3385 it->tab_line_p = window_wants_tab_line (w);
3386 it->header_line_p = window_wants_header_line (w);
3387 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3388 it->current_y = body_height + w->vscroll;
3389 }
3390
3391
3392 if (!FRAME_WINDOW_P (it->f)
3393 && !WINDOW_RIGHTMOST_P (it->w))
3394 it->last_visible_x -= 1;
3395
3396 it->last_visible_y = window_text_bottom_y (w);
3397 body_height += it->last_visible_y;
3398 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3399 && body_height != w->old_body_pixel_height)
3400 FRAME_WINDOW_CHANGE (it->f) = true;
3401
3402
3403
3404 if (base_face_id != DEFAULT_FACE_ID)
3405 {
3406 struct face *face;
3407
3408 it->face_id = remapped_base_face_id;
3409
3410
3411
3412 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3413 if (face && face->box != FACE_NO_BOX)
3414 {
3415 int box_thickness = face->box_vertical_line_width;
3416 it->face_box_p = true;
3417 it->start_of_box_run_p = true;
3418
3419
3420 if (box_thickness > 0)
3421 it->last_visible_x -= box_thickness;
3422 }
3423 }
3424
3425
3426
3427 if (charpos >= BUF_BEG (current_buffer))
3428 {
3429 it->stop_charpos = charpos;
3430 it->end_charpos = ZV;
3431 eassert (charpos == BYTE_TO_CHAR (bytepos));
3432 IT_CHARPOS (*it) = charpos;
3433 IT_BYTEPOS (*it) = bytepos;
3434
3435
3436
3437 it->face_id = it->base_face_id;
3438
3439 it->start = it->current;
3440
3441
3442
3443
3444
3445
3446
3447 it->bidi_p =
3448 !redisplay__inhibit_bidi
3449 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3450 && it->multibyte_p;
3451
3452
3453
3454 if (it->bidi_p)
3455 {
3456
3457
3458
3459
3460 if (base_face_id == DEFAULT_FACE_ID
3461 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3462 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3463 {
3464 if (it->line_wrap == TRUNCATE)
3465 it->last_visible_x -= it->truncation_pixel_width;
3466 else
3467 it->last_visible_x -= it->continuation_pixel_width;
3468 }
3469
3470
3471 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3472 Qleft_to_right))
3473 it->paragraph_embedding = L2R;
3474 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3475 Qright_to_left))
3476 it->paragraph_embedding = R2L;
3477 else
3478 it->paragraph_embedding = NEUTRAL_DIR;
3479 bidi_unshelve_cache (NULL, false);
3480 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3481 &it->bidi_it);
3482 }
3483
3484
3485
3486 it->medium_narrowing_begv = 0;
3487
3488
3489 reseat (it, it->current.pos, true);
3490 }
3491
3492 CHECK_IT (it);
3493 }
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581 static int
3582 get_narrowed_width (struct window *w)
3583 {
3584
3585
3586 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3587
3588
3589
3590 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3591 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3592 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3593 return fact * max (1, width);
3594 }
3595
3596 static int
3597 get_narrowed_len (struct window *w)
3598 {
3599 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3600 return get_narrowed_width (w) * max (1, height);
3601 }
3602
3603 static ptrdiff_t
3604 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3605 {
3606 int len = get_narrowed_len (w);
3607 return max ((pos / len - 1) * len, BEGV);
3608 }
3609
3610 static ptrdiff_t
3611 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3612 {
3613 int len = get_narrowed_len (w);
3614 return min ((pos / len + 1) * len, ZV);
3615 }
3616
3617
3618
3619
3620
3621
3622 static ptrdiff_t
3623 get_nearby_bol_pos (ptrdiff_t pos)
3624 {
3625 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3626 int dist;
3627 for (dist = 500; dist <= 500000; dist *= 10)
3628 {
3629 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3630 start = pos - dist < BEGV ? BEGV : pos - dist;
3631 for (cur = start; cur < pos; cur = next)
3632 {
3633 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3634 pos, pos_bytepos,
3635 1, &found, NULL, false);
3636 if (found)
3637 bol = next;
3638 else
3639 break;
3640 }
3641 if (bol >= BEGV || start == BEGV)
3642 break;
3643 else
3644 pos = pos - dist < BEGV ? BEGV : pos - dist;
3645 }
3646 eassert (bol <= init_pos);
3647 return bol;
3648 }
3649
3650 ptrdiff_t
3651 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3652 {
3653 int len = get_narrowed_width (w);
3654 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3655 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3656 }
3657
3658 ptrdiff_t
3659 get_large_narrowing_begv (ptrdiff_t pos)
3660 {
3661 if (long_line_optimizations_region_size <= 0)
3662 return BEGV;
3663 int len = long_line_optimizations_region_size / 2;
3664 int begv = max (pos - len, BEGV);
3665 int limit = long_line_optimizations_bol_search_limit;
3666 while (limit > 0)
3667 {
3668 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3669 return begv;
3670 begv--;
3671 limit--;
3672 }
3673 return begv;
3674 }
3675
3676 ptrdiff_t
3677 get_large_narrowing_zv (ptrdiff_t pos)
3678 {
3679 if (long_line_optimizations_region_size <= 0)
3680 return ZV;
3681 int len = long_line_optimizations_region_size / 2;
3682 return min (pos + len, ZV);
3683 }
3684
3685 static void
3686 unwind_narrowed_begv (Lisp_Object point_min)
3687 {
3688 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3689 }
3690
3691
3692
3693
3694 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3695 do { \
3696 if (IT->medium_narrowing_begv) \
3697 { \
3698 specpdl_ref count = SPECPDL_INDEX (); \
3699 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3700 SET_BUF_BEGV (current_buffer, BV); \
3701 DST = EXPR; \
3702 unbind_to (count, Qnil); \
3703 } \
3704 else \
3705 DST = EXPR; \
3706 } while (0)
3707
3708
3709
3710 void
3711 start_display (struct it *it, struct window *w, struct text_pos pos)
3712 {
3713 struct glyph_row *row;
3714 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3715
3716 row = w->desired_matrix->rows + first_vpos;
3717 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3718 it->first_vpos = first_vpos;
3719
3720
3721
3722 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3723 {
3724 int first_y = it->current_y;
3725
3726
3727
3728 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3729 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3730 if (!start_at_line_beg_p)
3731 {
3732 int new_x;
3733
3734 reseat_at_previous_visible_line_start (it);
3735 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3736
3737 new_x = it->current_x + it->pixel_width;
3738
3739
3740
3741
3742
3743
3744
3745 if (it->current_x > 0
3746 && it->line_wrap != TRUNCATE
3747 && (
3748 new_x > it->last_visible_x
3749
3750
3751 || (new_x == it->last_visible_x
3752 && FRAME_WINDOW_P (it->f)
3753 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3754 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3755 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3756 {
3757 if ((it->current.dpvec_index >= 0
3758 || it->current.overlay_string_index >= 0)
3759
3760
3761
3762
3763
3764 && it->c != '\n')
3765 {
3766 set_iterator_to_next (it, true);
3767 move_it_in_display_line_to (it, -1, -1, 0);
3768 }
3769
3770 it->continuation_lines_width += it->current_x;
3771 }
3772
3773
3774
3775
3776
3777 else if (it->current.dpvec_index >= 0)
3778 it->current.dpvec_index = 0;
3779
3780
3781
3782
3783 it->max_ascent = it->max_descent = 0;
3784 it->max_phys_ascent = it->max_phys_descent = 0;
3785
3786 it->current_y = first_y;
3787 it->vpos = 0;
3788 it->current_x = it->hpos = 0;
3789 }
3790 }
3791 }
3792
3793
3794
3795
3796
3797 static bool
3798 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3799 {
3800 Lisp_Object prop, window;
3801 bool ellipses_p = false;
3802 ptrdiff_t charpos = CHARPOS (pos->pos);
3803
3804
3805
3806
3807
3808 if (pos->dpvec_index >= 0
3809 && pos->overlay_string_index < 0
3810 && CHARPOS (pos->string_pos) < 0
3811 && charpos > BEGV
3812 && (XSETWINDOW (window, w),
3813 prop = Fget_char_property (make_fixnum (charpos),
3814 Qinvisible, window),
3815 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3816 {
3817 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3818 window);
3819 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3820 }
3821
3822 return ellipses_p;
3823 }
3824
3825
3826
3827
3828
3829
3830
3831 static bool
3832 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3833 {
3834 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3835 int i;
3836 bool overlay_strings_with_newlines = false;
3837
3838
3839
3840
3841
3842 if (in_ellipses_for_invisible_text_p (pos, w))
3843 {
3844 --charpos;
3845 bytepos = 0;
3846 }
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3858
3859
3860
3861
3862 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3863 {
3864 const char *s = SSDATA (it->overlay_strings[i]);
3865 const char *e = s + SBYTES (it->overlay_strings[i]);
3866
3867 while (s < e && *s != '\n')
3868 ++s;
3869
3870 if (s < e)
3871 {
3872 overlay_strings_with_newlines = true;
3873 break;
3874 }
3875 }
3876
3877
3878
3879 if (pos->overlay_string_index >= 0)
3880 {
3881 int relative_index;
3882
3883
3884
3885
3886
3887 if (it->method == GET_FROM_IMAGE)
3888 pop_it (it);
3889
3890
3891
3892
3893 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3894 {
3895 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3896 it->current.overlay_string_index = 0;
3897 while (n--)
3898 {
3899 load_overlay_strings (it, 0);
3900 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3901 }
3902 }
3903
3904 it->current.overlay_string_index = pos->overlay_string_index;
3905 relative_index = (it->current.overlay_string_index
3906 % OVERLAY_STRING_CHUNK_SIZE);
3907 it->string = it->overlay_strings[relative_index];
3908 eassert (STRINGP (it->string));
3909 it->current.string_pos = pos->string_pos;
3910 it->method = GET_FROM_STRING;
3911 it->end_charpos = SCHARS (it->string);
3912
3913 if (it->bidi_p)
3914 {
3915 it->bidi_it.string.lstring = it->string;
3916 it->bidi_it.string.s = NULL;
3917 it->bidi_it.string.schars = SCHARS (it->string);
3918 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3919 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3920 it->bidi_it.string.unibyte = !it->multibyte_p;
3921 it->bidi_it.w = it->w;
3922 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3923 FRAME_WINDOW_P (it->f), &it->bidi_it);
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933 if (CHARPOS (pos->string_pos) == 0)
3934 {
3935 get_visually_first_element (it);
3936 if (IT_STRING_CHARPOS (*it) != 0)
3937 do {
3938
3939 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3940 bidi_move_to_visually_next (&it->bidi_it);
3941 } while (it->bidi_it.charpos != 0);
3942 }
3943 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3944 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3945 }
3946 }
3947
3948 if (CHARPOS (pos->string_pos) >= 0)
3949 {
3950
3951
3952
3953 it->current.string_pos = pos->string_pos;
3954 eassert (STRINGP (it->string));
3955 if (it->bidi_p)
3956 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3957 FRAME_WINDOW_P (it->f), &it->bidi_it);
3958 }
3959
3960
3961
3962 if (pos->dpvec_index >= 0)
3963 {
3964 if (it->dpvec == NULL)
3965 get_next_display_element (it);
3966 eassert (it->dpvec && it->current.dpvec_index == 0);
3967 it->current.dpvec_index = pos->dpvec_index;
3968 }
3969
3970 CHECK_IT (it);
3971 return !overlay_strings_with_newlines;
3972 }
3973
3974
3975
3976
3977
3978 static void
3979 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
3980 {
3981 init_from_display_pos (it, w, &row->start);
3982 it->start = row->start;
3983 it->continuation_lines_width = row->continuation_lines_width;
3984 CHECK_IT (it);
3985 }
3986
3987
3988
3989
3990
3991
3992
3993
3994 static bool
3995 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
3996 {
3997 bool success = false;
3998
3999 if (init_from_display_pos (it, w, &row->end))
4000 {
4001 if (row->continued_p)
4002 it->continuation_lines_width
4003 = row->continuation_lines_width + row->pixel_width;
4004 CHECK_IT (it);
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014 if (get_next_display_element (it)
4015 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4016 success = false;
4017 else
4018 success = true;
4019 }
4020
4021 return success;
4022 }
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035 static void
4036 handle_stop (struct it *it)
4037 {
4038 enum prop_handled handled;
4039 bool handle_overlay_change_p;
4040 struct props *p;
4041
4042 it->dpvec = NULL;
4043 it->current.dpvec_index = -1;
4044 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4045 it->ellipsis_p = false;
4046
4047
4048 if (it->selective_display_ellipsis_p)
4049 it->saved_face_id = it->face_id;
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093 do
4094 {
4095 handled = HANDLED_NORMALLY;
4096
4097
4098 for (p = it_props; p->handler; ++p)
4099 {
4100 handled = p->handler (it);
4101
4102 if (handled == HANDLED_RECOMPUTE_PROPS)
4103 break;
4104 else if (handled == HANDLED_RETURN)
4105 {
4106
4107
4108 if (!handle_overlay_change_p
4109 || it->sp > 1
4110
4111
4112
4113
4114
4115
4116 || (it->current.overlay_string_index < 0
4117 && !get_overlay_strings_1 (it, 0, false)))
4118 {
4119 if (it->ellipsis_p)
4120 setup_for_ellipsis (it, 0);
4121
4122
4123
4124
4125
4126 if (STRINGP (it->string) && !SCHARS (it->string))
4127 pop_it (it);
4128 return;
4129 }
4130 else if (STRINGP (it->string) && !SCHARS (it->string))
4131 pop_it (it);
4132 else
4133 {
4134 it->string_from_display_prop_p = false;
4135 it->from_disp_prop_p = false;
4136 handle_overlay_change_p = false;
4137 }
4138 handled = HANDLED_RECOMPUTE_PROPS;
4139 break;
4140 }
4141 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4142 handle_overlay_change_p = false;
4143 }
4144
4145 if (handled != HANDLED_RECOMPUTE_PROPS)
4146 {
4147
4148
4149 if (it->method == GET_FROM_DISPLAY_VECTOR)
4150 handle_overlay_change_p = false;
4151
4152
4153
4154
4155 if (handle_overlay_change_p)
4156 handled = handle_overlay_change (it);
4157 }
4158
4159 if (it->ellipsis_p)
4160 {
4161 setup_for_ellipsis (it, 0);
4162 break;
4163 }
4164 }
4165 while (handled == HANDLED_RECOMPUTE_PROPS);
4166
4167
4168 if (handled == HANDLED_NORMALLY)
4169 compute_stop_pos (it);
4170 }
4171
4172
4173
4174
4175
4176 static void
4177 compute_stop_pos (struct it *it)
4178 {
4179 register INTERVAL iv, next_iv;
4180 Lisp_Object object, limit, position;
4181 ptrdiff_t charpos, bytepos, cmp_limit_pos = -1;
4182
4183 if (STRINGP (it->string))
4184 {
4185
4186
4187 it->stop_charpos = it->end_charpos;
4188 object = it->string;
4189 limit = Qnil;
4190 charpos = IT_STRING_CHARPOS (*it);
4191 bytepos = IT_STRING_BYTEPOS (*it);
4192 }
4193 else
4194 {
4195 ptrdiff_t pos;
4196
4197
4198
4199 if (it->end_charpos > ZV)
4200 it->end_charpos = ZV;
4201 it->stop_charpos = it->end_charpos;
4202
4203
4204
4205
4206
4207 charpos = IT_CHARPOS (*it);
4208 bytepos = IT_BYTEPOS (*it);
4209 pos = next_overlay_change (charpos);
4210 if (pos < it->stop_charpos)
4211 it->stop_charpos = pos;
4212
4213 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4214 && !NILP (Vauto_composition_mode)
4215 && composition_break_at_point
4216 && charpos < PT && PT < it->stop_charpos)
4217 it->stop_charpos = PT;
4218
4219
4220
4221 XSETBUFFER (object, current_buffer);
4222 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4223
4224
4225
4226
4227
4228
4229 if (!composition_break_at_point
4230 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4231 && !NILP (Vauto_composition_mode))
4232 {
4233 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4234 bool found = false;
4235
4236 if (pos > ZV)
4237 pos = ZV;
4238 if (endpos > ZV)
4239 endpos = ZV;
4240 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4241 while (pos < endpos)
4242 {
4243 int ch = fetch_char_advance_no_check (&pos, &bpos);
4244 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4245 {
4246 found = true;
4247 break;
4248 }
4249 }
4250 if (found)
4251 {
4252 pos--;
4253 cmp_limit_pos = pos;
4254 }
4255 else if (it->stop_charpos < endpos)
4256 pos = it->stop_charpos;
4257 else
4258 {
4259
4260 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4261 }
4262 }
4263 limit = make_fixnum (pos);
4264 }
4265
4266
4267
4268 position = make_fixnum (charpos);
4269 iv = validate_interval_range (object, &position, &position, false);
4270 if (iv)
4271 {
4272 Lisp_Object values_here[LAST_PROP_IDX];
4273 struct props *p;
4274
4275
4276 for (p = it_props; p->handler; ++p)
4277 values_here[p->idx] = textget (iv->plist,
4278 builtin_lisp_symbol (p->name));
4279
4280
4281
4282 for (next_iv = next_interval (iv);
4283 (next_iv
4284 && (NILP (limit)
4285 || XFIXNAT (limit) > next_iv->position));
4286 next_iv = next_interval (next_iv))
4287 {
4288 for (p = it_props; p->handler; ++p)
4289 {
4290 Lisp_Object new_value = textget (next_iv->plist,
4291 builtin_lisp_symbol (p->name));
4292 if (!EQ (values_here[p->idx], new_value))
4293 break;
4294 }
4295
4296 if (p->handler)
4297 break;
4298 }
4299
4300 if (next_iv)
4301 {
4302 if (FIXNUMP (limit)
4303 && next_iv->position >= XFIXNAT (limit))
4304
4305 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4306 else
4307
4308 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4309 }
4310 }
4311
4312 if (it->cmp_it.id < 0
4313 && (STRINGP (it->string)
4314 || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
4315 && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
4316 {
4317 ptrdiff_t stoppos = it->end_charpos;
4318
4319
4320
4321
4322 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4323 stoppos = -1;
4324 else if (cmp_limit_pos > 0)
4325 stoppos = cmp_limit_pos;
4326
4327
4328
4329 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4330 stoppos, it->string, false);
4331 }
4332
4333 eassert (STRINGP (it->string)
4334 || (it->stop_charpos >= BEGV
4335 && it->stop_charpos >= IT_CHARPOS (*it)));
4336 }
4337
4338
4339
4340
4341 #define MAX_DISP_SCAN 250
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355 ptrdiff_t
4356 compute_display_string_pos (struct text_pos *position,
4357 struct bidi_string_data *string,
4358 struct window *w,
4359 bool frame_window_p, int *disp_prop)
4360 {
4361
4362 Lisp_Object object, object1;
4363 Lisp_Object pos, spec, limpos;
4364 bool string_p = string && (STRINGP (string->lstring) || string->s);
4365 ptrdiff_t eob = string_p ? string->schars : ZV;
4366 ptrdiff_t begb = string_p ? 0 : BEGV;
4367 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4368 ptrdiff_t lim =
4369 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4370 struct text_pos tpos;
4371 int rv = 0;
4372
4373 if (string && STRINGP (string->lstring))
4374 object1 = object = string->lstring;
4375 else if (w && !string_p)
4376 {
4377 XSETWINDOW (object, w);
4378 object1 = Qnil;
4379 }
4380 else
4381 object1 = object = Qnil;
4382
4383 *disp_prop = 1;
4384
4385 if (charpos >= eob
4386
4387
4388 || string->from_disp_str
4389
4390 || (string->s && !STRINGP (object)))
4391 {
4392 *disp_prop = 0;
4393 return eob;
4394 }
4395
4396
4397
4398 pos = make_fixnum (charpos);
4399 if (STRINGP (object))
4400 bufpos = string->bufpos;
4401 else
4402 bufpos = charpos;
4403 tpos = *position;
4404 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4405 && (charpos <= begb
4406 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4407 object),
4408 spec))
4409 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4410 frame_window_p)))
4411 {
4412 if (rv == 2)
4413 *disp_prop = 2;
4414 return charpos;
4415 }
4416
4417
4418
4419 limpos = make_fixnum (lim);
4420 do {
4421 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4422 CHARPOS (tpos) = XFIXNAT (pos);
4423 if (CHARPOS (tpos) >= lim)
4424 {
4425 *disp_prop = 0;
4426 break;
4427 }
4428 if (STRINGP (object))
4429 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4430 else
4431 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4432 spec = Fget_char_property (pos, Qdisplay, object);
4433 if (!STRINGP (object))
4434 bufpos = CHARPOS (tpos);
4435 } while (NILP (spec)
4436 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4437 bufpos, frame_window_p)));
4438 if (rv == 2)
4439 *disp_prop = 2;
4440
4441 return CHARPOS (tpos);
4442 }
4443
4444
4445
4446
4447
4448
4449 ptrdiff_t
4450 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4451 {
4452
4453 Lisp_Object object =
4454 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4455 Lisp_Object pos = make_fixnum (charpos);
4456 ptrdiff_t eob =
4457 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4458
4459 if (charpos >= eob || (string->s && !STRINGP (object)))
4460 return eob;
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4477 return -1;
4478
4479
4480
4481 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4482
4483 return XFIXNAT (pos);
4484 }
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496 static enum prop_handled
4497 handle_fontified_prop (struct it *it)
4498 {
4499 Lisp_Object prop, pos;
4500 enum prop_handled handled = HANDLED_NORMALLY;
4501
4502 if (!NILP (Vmemory_full))
4503 return handled;
4504
4505
4506
4507
4508
4509 if (!STRINGP (it->string)
4510 && it->s == NULL
4511 && !NILP (Vfontification_functions)
4512 && !(input_was_pending && redisplay_skip_fontification_on_input)
4513 && !NILP (Vrun_hooks)
4514 && (pos = make_fixnum (IT_CHARPOS (*it)),
4515 prop = Fget_char_property (pos, Qfontified, Qnil),
4516
4517
4518 NILP (prop) && IT_CHARPOS (*it) < Z))
4519 {
4520 specpdl_ref count = SPECPDL_INDEX ();
4521 Lisp_Object val;
4522 struct buffer *obuf = current_buffer;
4523 ptrdiff_t begv = BEGV, zv = ZV;
4524 bool old_clip_changed = current_buffer->clip_changed;
4525 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4526
4527 val = Vfontification_functions;
4528 specbind (Qfontification_functions, Qnil);
4529
4530 eassert (it->end_charpos == ZV);
4531
4532 if (current_buffer->long_line_optimizations_p
4533 && long_line_optimizations_region_size > 0)
4534 {
4535 ptrdiff_t begv = it->large_narrowing_begv;
4536 ptrdiff_t zv = it->large_narrowing_zv;
4537 ptrdiff_t charpos = IT_CHARPOS (*it);
4538 if (charpos < begv || charpos > zv)
4539 {
4540 begv = get_large_narrowing_begv (charpos);
4541 zv = get_large_narrowing_zv (charpos);
4542 }
4543 if (begv != BEG || zv != Z)
4544 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4545 Qlong_line_optimizations_in_fontification_functions);
4546 }
4547
4548
4549
4550 it->f->inhibit_clear_image_cache = true;
4551
4552 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4553 safe_call1 (val, pos);
4554 else
4555 {
4556 Lisp_Object fns, fn;
4557
4558 fns = Qnil;
4559
4560 for (; CONSP (val); val = XCDR (val))
4561 {
4562 fn = XCAR (val);
4563
4564 if (EQ (fn, Qt))
4565 {
4566
4567
4568
4569
4570
4571 for (fns = Fdefault_value (Qfontification_functions);
4572 CONSP (fns);
4573 fns = XCDR (fns))
4574 {
4575 fn = XCAR (fns);
4576 if (!EQ (fn, Qt))
4577 safe_call1 (fn, pos);
4578 }
4579 }
4580 else
4581 safe_call1 (fn, pos);
4582 }
4583 }
4584
4585 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4586 unbind_to (count, Qnil);
4587
4588
4589
4590
4591
4592
4593
4594
4595 if (obuf == current_buffer)
4596 {
4597 if (begv == BEGV && zv == ZV)
4598 current_buffer->clip_changed = old_clip_changed;
4599 }
4600
4601
4602 else if (BUFFER_LIVE_P (obuf))
4603 set_buffer_internal_1 (obuf);
4604
4605
4606
4607
4608
4609
4610 it->end_charpos = ZV;
4611
4612
4613
4614
4615 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4616 handled = HANDLED_RECOMPUTE_PROPS;
4617 }
4618
4619 return handled;
4620 }
4621
4622
4623
4624
4625
4626
4627
4628 static int
4629 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4630 {
4631 ptrdiff_t next_stop;
4632
4633 if (!STRINGP (it->string))
4634 {
4635 return face_at_buffer_position (it->w,
4636 IT_CHARPOS (*it),
4637 &next_stop,
4638 (IT_CHARPOS (*it)
4639 + TEXT_PROP_DISTANCE_LIMIT),
4640 false, it->base_face_id,
4641 attr_filter);
4642 }
4643 else
4644 {
4645 int base_face_id;
4646 ptrdiff_t bufpos;
4647 int i;
4648 Lisp_Object from_overlay
4649 = (it->current.overlay_string_index >= 0
4650 ? it->string_overlays[it->current.overlay_string_index
4651 % OVERLAY_STRING_CHUNK_SIZE]
4652 : Qnil);
4653
4654
4655
4656
4657
4658
4659
4660 if (! NILP (from_overlay))
4661 for (i = it->sp - 1; i >= 0; i--)
4662 {
4663 if (it->stack[i].current.overlay_string_index >= 0)
4664 from_overlay
4665 = it->string_overlays[it->stack[i].current.overlay_string_index
4666 % OVERLAY_STRING_CHUNK_SIZE];
4667 else if (! NILP (it->stack[i].from_overlay))
4668 from_overlay = it->stack[i].from_overlay;
4669
4670 if (!NILP (from_overlay))
4671 break;
4672 }
4673
4674 if (! NILP (from_overlay))
4675 {
4676 bufpos = IT_CHARPOS (*it);
4677
4678
4679 base_face_id
4680 = face_for_overlay_string (it->w,
4681 IT_CHARPOS (*it),
4682 &next_stop,
4683 (IT_CHARPOS (*it)
4684 + TEXT_PROP_DISTANCE_LIMIT),
4685 false,
4686 from_overlay, attr_filter);
4687 }
4688 else
4689 {
4690 bufpos = 0;
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708 base_face_id = it->string_from_prefix_prop_p
4709 ? (!NILP (Vface_remapping_alist)
4710 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4711 : DEFAULT_FACE_ID)
4712 : underlying_face_id (it);
4713 }
4714
4715 return face_at_string_position (it->w,
4716 it->string,
4717 IT_STRING_CHARPOS (*it),
4718 bufpos,
4719 &next_stop,
4720 base_face_id, false,
4721 attr_filter);
4722 }
4723 }
4724
4725
4726
4727
4728 static enum prop_handled
4729 handle_face_prop (struct it *it)
4730 {
4731 specpdl_ref count = SPECPDL_INDEX ();
4732
4733
4734
4735 specbind (Qinhibit_quit, Qt);
4736 const int new_face_id = face_at_pos (it, 0);
4737 unbind_to (count, Qnil);
4738
4739
4740
4741
4742
4743
4744
4745
4746 if (new_face_id != it->face_id)
4747 {
4748 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4749
4750
4751
4752 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4753
4754
4755
4756
4757 if (!STRINGP (it->string)
4758 && !old_face
4759 && IT_CHARPOS (*it) > BEG)
4760 {
4761 const int prev_face_id = face_before_it_pos (it);
4762
4763 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4764 }
4765
4766
4767
4768
4769 it->face_id = new_face_id;
4770
4771
4772 if (!(it->start_of_box_run_p && old_face && old_face->box))
4773 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4774 && (old_face == NULL || !old_face->box));
4775 it->face_box_p = new_face->box != FACE_NO_BOX;
4776 }
4777
4778 return HANDLED_NORMALLY;
4779 }
4780
4781
4782
4783
4784
4785
4786
4787 static int
4788 underlying_face_id (const struct it *it)
4789 {
4790 int face_id = it->base_face_id, i;
4791
4792 eassert (STRINGP (it->string));
4793
4794 for (i = it->sp - 1; i >= 0; --i)
4795 if (NILP (it->stack[i].string))
4796 face_id = it->stack[i].face_id;
4797
4798 return face_id;
4799 }
4800
4801
4802
4803
4804
4805
4806
4807 static int
4808 face_before_or_after_it_pos (struct it *it, bool before_p)
4809 {
4810 int face_id, limit;
4811 ptrdiff_t next_check_charpos;
4812 struct it it_copy;
4813 void *it_copy_data = NULL;
4814
4815 eassert (it->s == NULL);
4816
4817 if (STRINGP (it->string))
4818 {
4819 ptrdiff_t bufpos, charpos;
4820 int base_face_id;
4821
4822
4823
4824
4825
4826 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4827 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4828 || it->current_x <= it->first_visible_x)
4829 return it->face_id;
4830
4831 if (!it->bidi_p)
4832 {
4833
4834
4835
4836 if (before_p)
4837 charpos = IT_STRING_CHARPOS (*it) - 1;
4838 else if (it->what == IT_COMPOSITION)
4839
4840
4841 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4842 else
4843 charpos = IT_STRING_CHARPOS (*it) + 1;
4844 }
4845 else
4846 {
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857 SAVE_IT (it_copy, *it, it_copy_data);
4858 IT_STRING_CHARPOS (it_copy) = 0;
4859 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4860 it_copy.bidi_it.scan_dir = 0;
4861
4862 do
4863 {
4864 charpos = it_copy.bidi_it.charpos;
4865 if (charpos >= SCHARS (it->string))
4866 break;
4867 bidi_move_to_visually_next (&it_copy.bidi_it);
4868 }
4869 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4870
4871 if (!before_p)
4872 {
4873
4874
4875
4876 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4877
4878
4879
4880 if (it_copy.bidi_it.first_elt)
4881 n++;
4882 while (n--)
4883 bidi_move_to_visually_next (&it_copy.bidi_it);
4884
4885 charpos = it_copy.bidi_it.charpos;
4886 }
4887
4888 RESTORE_IT (it, it, it_copy_data);
4889 }
4890 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4891
4892 if (it->current.overlay_string_index >= 0)
4893 bufpos = IT_CHARPOS (*it);
4894 else
4895 bufpos = 0;
4896
4897 base_face_id = underlying_face_id (it);
4898
4899
4900 face_id = face_at_string_position (it->w, it->string, charpos,
4901 bufpos, &next_check_charpos,
4902 base_face_id, false, 0);
4903
4904
4905
4906
4907 if (STRING_MULTIBYTE (it->string))
4908 {
4909 struct text_pos pos1 = string_pos (charpos, it->string);
4910 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4911 struct face *face = FACE_FROM_ID (it->f, face_id);
4912 int len, c = check_char_and_length (p, &len);
4913 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4914 }
4915 }
4916 else
4917 {
4918 struct text_pos pos;
4919
4920 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4921 || (IT_CHARPOS (*it) <= BEGV && before_p))
4922 return it->face_id;
4923
4924 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4925 pos = it->current.pos;
4926
4927 if (!it->bidi_p)
4928 {
4929 if (before_p)
4930 DEC_TEXT_POS (pos, it->multibyte_p);
4931 else
4932 {
4933 if (it->what == IT_COMPOSITION)
4934 {
4935
4936
4937 pos.charpos += it->cmp_it.nchars;
4938 pos.bytepos += it->len;
4939 }
4940 else
4941 INC_TEXT_POS (pos, it->multibyte_p);
4942 }
4943 }
4944 else
4945 {
4946 if (before_p)
4947 {
4948 int current_x;
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959 if (it->current_x <= it->first_visible_x)
4960 return it->face_id;
4961 SAVE_IT (it_copy, *it, it_copy_data);
4962
4963
4964
4965
4966
4967 current_x = it_copy.current_x;
4968 move_it_vertically_backward (&it_copy, 0);
4969 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
4970 pos = it_copy.current.pos;
4971 RESTORE_IT (it, it, it_copy_data);
4972 }
4973 else
4974 {
4975
4976
4977
4978 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4979
4980 it_copy = *it;
4981
4982
4983
4984 if (it->bidi_it.first_elt)
4985 n++;
4986 while (n--)
4987 bidi_move_to_visually_next (&it_copy.bidi_it);
4988
4989 SET_TEXT_POS (pos,
4990 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
4991 }
4992 }
4993 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
4994
4995
4996 face_id = face_at_buffer_position (it->w,
4997 CHARPOS (pos),
4998 &next_check_charpos,
4999 limit, false, -1, 0);
5000
5001
5002
5003
5004 if (it->multibyte_p)
5005 {
5006 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
5007 struct face *face = FACE_FROM_ID (it->f, face_id);
5008 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5009 }
5010 }
5011
5012 return face_id;
5013 }
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024 static enum prop_handled
5025 handle_invisible_prop (struct it *it)
5026 {
5027 enum prop_handled handled = HANDLED_NORMALLY;
5028 int invis;
5029 Lisp_Object prop;
5030
5031 if (STRINGP (it->string))
5032 {
5033 Lisp_Object end_charpos, limit;
5034
5035
5036
5037
5038 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5039 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5040 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5041
5042 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5043 {
5044
5045
5046 bool display_ellipsis_p = (invis == 2);
5047 ptrdiff_t len, endpos;
5048
5049 handled = HANDLED_RECOMPUTE_PROPS;
5050
5051
5052
5053 endpos = len = SCHARS (it->string);
5054 XSETINT (limit, len);
5055 do
5056 {
5057 end_charpos
5058 = Fnext_single_property_change (end_charpos, Qinvisible,
5059 it->string, limit);
5060
5061
5062 eassert (FIXNUMP (end_charpos));
5063 if (FIXNUMP (end_charpos))
5064 {
5065 endpos = XFIXNAT (end_charpos);
5066 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5067 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5068 if (invis == 2)
5069 display_ellipsis_p = true;
5070 }
5071 else
5072 endpos = len;
5073 }
5074 while (invis != 0 && endpos < len);
5075
5076 if (display_ellipsis_p)
5077 it->ellipsis_p = true;
5078
5079 if (endpos < len)
5080 {
5081
5082 struct text_pos old;
5083 ptrdiff_t oldpos;
5084
5085 old = it->current.string_pos;
5086 oldpos = CHARPOS (old);
5087 if (it->bidi_p)
5088 {
5089 if (it->bidi_it.first_elt
5090 && it->bidi_it.charpos < SCHARS (it->string))
5091 bidi_paragraph_init (it->paragraph_embedding,
5092 &it->bidi_it, true);
5093
5094 do
5095 {
5096 bidi_move_to_visually_next (&it->bidi_it);
5097 }
5098 while (oldpos <= it->bidi_it.charpos
5099 && it->bidi_it.charpos < endpos
5100 && it->bidi_it.charpos < it->bidi_it.string.schars);
5101
5102 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5103 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5104 if (IT_CHARPOS (*it) >= endpos)
5105 it->prev_stop = endpos;
5106 }
5107 else
5108 {
5109 IT_STRING_CHARPOS (*it) = endpos;
5110 compute_string_pos (&it->current.string_pos, old, it->string);
5111 }
5112 }
5113 else
5114 {
5115
5116
5117
5118 if (it->current.overlay_string_index >= 0
5119 && !display_ellipsis_p)
5120 {
5121 next_overlay_string (it);
5122
5123
5124 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5125 }
5126 else
5127 {
5128 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5129 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5130 }
5131 }
5132 }
5133 }
5134 else
5135 {
5136 ptrdiff_t newpos, next_stop, start_charpos, tem;
5137 Lisp_Object pos, overlay;
5138
5139
5140 tem = start_charpos = IT_CHARPOS (*it);
5141 pos = make_fixnum (tem);
5142 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5143 &overlay);
5144 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5145
5146
5147 if (invis != 0 && start_charpos < it->end_charpos)
5148 {
5149
5150
5151 bool display_ellipsis_p = invis == 2;
5152
5153 handled = HANDLED_RECOMPUTE_PROPS;
5154
5155
5156
5157 do
5158 {
5159
5160
5161
5162
5163
5164 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5165
5166
5167
5168
5169 if (newpos == tem || newpos >= ZV)
5170 invis = 0;
5171 else
5172 {
5173
5174
5175
5176
5177
5178
5179 pos = make_fixnum (newpos);
5180 prop = Fget_char_property (pos, Qinvisible, it->window);
5181 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5182 }
5183
5184
5185
5186 if (invis != 0)
5187 tem = next_stop;
5188
5189
5190
5191 if (invis == 2)
5192 display_ellipsis_p = true;
5193 }
5194 while (invis != 0);
5195
5196
5197 if (it->bidi_p)
5198 {
5199 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5200 bool on_newline
5201 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5202 bool after_newline
5203 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5204
5205
5206
5207
5208
5209
5210
5211
5212 if (on_newline || after_newline)
5213 {
5214 struct text_pos tpos;
5215 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5216
5217 SET_TEXT_POS (tpos, newpos, bpos);
5218 reseat_1 (it, tpos, false);
5219
5220
5221
5222
5223
5224 if (on_newline)
5225 {
5226 it->bidi_it.first_elt = false;
5227 it->bidi_it.paragraph_dir = pdir;
5228 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5229 it->bidi_it.nchars = 1;
5230 it->bidi_it.ch_len = 1;
5231 }
5232 }
5233 else
5234 {
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5246 {
5247
5248
5249
5250
5251
5252
5253
5254 bidi_paragraph_init (it->paragraph_embedding,
5255 &it->bidi_it, true);
5256 }
5257 do
5258 {
5259 bidi_move_to_visually_next (&it->bidi_it);
5260 }
5261 while (it->stop_charpos <= it->bidi_it.charpos
5262 && it->bidi_it.charpos < newpos);
5263 IT_CHARPOS (*it) = it->bidi_it.charpos;
5264 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5265
5266
5267
5268
5269 if (IT_CHARPOS (*it) >= newpos)
5270 it->prev_stop = newpos;
5271 }
5272 }
5273 else
5274 {
5275 IT_CHARPOS (*it) = newpos;
5276 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5277 }
5278
5279 if (display_ellipsis_p)
5280 {
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293 if (!STRINGP (it->object))
5294 {
5295 it->position.charpos = newpos - 1;
5296 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5297 }
5298 }
5299
5300
5301
5302
5303
5304
5305
5306 if (NILP (overlay)
5307 && get_overlay_strings (it, it->stop_charpos))
5308 {
5309 handled = HANDLED_RECOMPUTE_PROPS;
5310 if (it->sp > 0)
5311 {
5312 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325 it->stack[it->sp - 1].stop_charpos
5326 = CHARPOS (it->stack[it->sp - 1].current.pos);
5327 }
5328 }
5329 else if (display_ellipsis_p)
5330 {
5331 it->ellipsis_p = true;
5332
5333
5334
5335 handled = HANDLED_RETURN;
5336 }
5337 }
5338 }
5339
5340 return handled;
5341 }
5342
5343
5344
5345
5346
5347 static void
5348 setup_for_ellipsis (struct it *it, int len)
5349 {
5350
5351
5352 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5353 {
5354 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5355 it->dpvec = v->contents;
5356 it->dpend = v->contents + v->header.size;
5357 }
5358 else
5359 {
5360
5361 it->dpvec = default_invis_vector;
5362 it->dpend = default_invis_vector + 3;
5363 }
5364
5365 it->dpvec_char_len = len;
5366 it->current.dpvec_index = 0;
5367 it->dpvec_face_id = -1;
5368
5369
5370
5371
5372
5373
5374
5375
5376 if (it->saved_face_id >= 0)
5377 it->face_id = it->saved_face_id;
5378
5379
5380
5381 if (it->method == GET_FROM_BUFFER)
5382 it->ignore_overlay_strings_at_pos_p = false;
5383
5384 it->method = GET_FROM_DISPLAY_VECTOR;
5385 it->ellipsis_p = true;
5386 }
5387
5388
5389 static Lisp_Object
5390 find_display_property (Lisp_Object disp, Lisp_Object prop)
5391 {
5392 if (NILP (disp))
5393 return Qnil;
5394
5395 if (VECTORP (disp))
5396 {
5397 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5398 {
5399 Lisp_Object elem = AREF (disp, i);
5400 if (CONSP (elem)
5401 && CONSP (XCDR (elem))
5402 && EQ (XCAR (elem), prop))
5403 return XCAR (XCDR (elem));
5404 }
5405 return Qnil;
5406 }
5407
5408 else if (CONSP (disp)
5409 && CONSP (XCAR (disp)))
5410 {
5411 while (!NILP (disp))
5412 {
5413 Lisp_Object elem = XCAR (disp);
5414 if (CONSP (elem)
5415 && CONSP (XCDR (elem))
5416 && EQ (XCAR (elem), prop))
5417 return XCAR (XCDR (elem));
5418
5419
5420
5421 if (CONSP (XCDR (disp)))
5422 disp = XCDR (disp);
5423 else
5424 disp = Qnil;
5425 }
5426 return Qnil;
5427 }
5428
5429 else if (CONSP (disp)
5430 && CONSP (XCDR (disp))
5431 && EQ (XCAR (disp), prop))
5432 return XCAR (XCDR (disp));
5433 else
5434 return Qnil;
5435 }
5436
5437 static Lisp_Object
5438 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5439 {
5440 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5441 Qdisplay, object),
5442 prop);
5443 }
5444
5445 static void
5446 display_min_width (struct it *it, ptrdiff_t bufpos,
5447 Lisp_Object object, Lisp_Object width_spec)
5448 {
5449
5450
5451 if (!NILP (it->min_width_property)
5452 && !EQ (width_spec, it->min_width_property))
5453 {
5454 if (!it->glyph_row)
5455 return;
5456
5457
5458
5459
5460
5461 if ((bufpos == 0
5462 && !EQ (it->min_width_property,
5463 get_display_property (0, Qmin_width, object)))
5464
5465
5466 || (bufpos > BEGV
5467 && EQ (it->min_width_property,
5468 get_display_property (bufpos - 1, Qmin_width, object))))
5469 {
5470 Lisp_Object w = Qnil;
5471 double width;
5472 #ifdef HAVE_WINDOW_SYSTEM
5473 if (FRAME_WINDOW_P (it->f))
5474 {
5475 struct font *font = NULL;
5476 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5477 font = face->font ? face->font : FRAME_FONT (it->f);
5478 calc_pixel_width_or_height (&width, it,
5479 XCAR (it->min_width_property),
5480 font, true, NULL);
5481 width -= it->current_x - it->min_width_start;
5482 w = list1 (make_int (width));
5483 }
5484 else
5485 #endif
5486 {
5487 calc_pixel_width_or_height (&width, it,
5488 XCAR (it->min_width_property),
5489 NULL, true, NULL);
5490 width -= (it->current_x - it->min_width_start) /
5491 FRAME_COLUMN_WIDTH (it->f);
5492 w = make_int (width);
5493 }
5494
5495
5496 it->object = list3 (Qspace, QCwidth, w);
5497 produce_stretch_glyph (it);
5498 if (it->area == TEXT_AREA)
5499 it->current_x += it->pixel_width;
5500 it->min_width_property = Qnil;
5501 }
5502 }
5503
5504
5505
5506
5507 if (CONSP (width_spec))
5508 {
5509 if (bufpos == BEGV
5510
5511 || (bufpos == 0
5512 && !EQ (it->min_width_property,
5513 get_display_property (0, Qmin_width, object)))
5514
5515 || (bufpos > BEGV
5516 && !EQ (width_spec,
5517 get_display_property (bufpos - 1, Qmin_width, object))))
5518 {
5519 it->min_width_property = width_spec;
5520 it->min_width_start = it->current_x;
5521 }
5522 }
5523 }
5524
5525 DEFUN ("get-display-property", Fget_display_property,
5526 Sget_display_property, 2, 4, 0,
5527 doc:
5528
5529
5530
5531
5532 )
5533 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5534 Lisp_Object properties)
5535 {
5536 if (NILP (properties))
5537 properties = Fget_text_property (position, Qdisplay, object);
5538 else
5539 CHECK_LIST (properties);
5540
5541 return find_display_property (properties, prop);
5542 }
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556 static enum prop_handled
5557 handle_display_prop (struct it *it)
5558 {
5559 Lisp_Object propval, object, overlay;
5560 struct text_pos *position;
5561 ptrdiff_t bufpos;
5562
5563 int display_replaced = 0;
5564
5565 if (STRINGP (it->string))
5566 {
5567 object = it->string;
5568 position = &it->current.string_pos;
5569 bufpos = CHARPOS (it->current.pos);
5570 }
5571 else
5572 {
5573 XSETWINDOW (object, it->w);
5574 position = &it->current.pos;
5575 bufpos = CHARPOS (*position);
5576 }
5577
5578
5579 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5580 it->space_width = Qnil;
5581 it->font_height = Qnil;
5582 it->voffset = 0;
5583
5584
5585
5586
5587 if (!it->string_from_display_prop_p)
5588 it->area = TEXT_AREA;
5589
5590 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5591 Qdisplay, object, &overlay);
5592
5593
5594 if (!STRINGP (it->string))
5595 object = it->w->contents;
5596
5597
5598 if (!NILP (it->min_width_property)
5599 && NILP (find_display_property (propval, Qmin_width)))
5600 display_min_width (it, bufpos, object, Qnil);
5601
5602 if (NILP (propval))
5603 return HANDLED_NORMALLY;
5604
5605
5606
5607 display_replaced = handle_display_spec (it, propval, object, overlay,
5608 position, bufpos,
5609 FRAME_WINDOW_P (it->f));
5610 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5611 }
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629 static int
5630 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5631 Lisp_Object overlay, struct text_pos *position,
5632 ptrdiff_t bufpos, bool frame_window_p)
5633 {
5634 int replacing = 0;
5635 bool enable_eval = true;
5636
5637
5638 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5639 {
5640 enable_eval = false;
5641 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5642 }
5643
5644 if (CONSP (spec)
5645
5646 && !EQ (XCAR (spec), Qimage)
5647 #ifdef HAVE_XWIDGETS
5648 && !EQ (XCAR (spec), Qxwidget)
5649 #endif
5650 && !EQ (XCAR (spec), Qspace)
5651 && !EQ (XCAR (spec), Qwhen)
5652 && !EQ (XCAR (spec), Qslice)
5653 && !EQ (XCAR (spec), Qspace_width)
5654 && !EQ (XCAR (spec), Qheight)
5655 && !EQ (XCAR (spec), Qraise)
5656
5657 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5658 && !EQ (XCAR (spec), Qleft_fringe)
5659 && !EQ (XCAR (spec), Qright_fringe)
5660 && !EQ (XCAR (spec), Qmin_width)
5661 && !NILP (XCAR (spec)))
5662 {
5663 for (; CONSP (spec); spec = XCDR (spec))
5664 {
5665 int rv = handle_single_display_spec (it, XCAR (spec), object,
5666 overlay, position, bufpos,
5667 replacing, frame_window_p,
5668 enable_eval);
5669 if (rv != 0)
5670 {
5671 replacing = rv;
5672
5673
5674 if (!it || STRINGP (object))
5675 break;
5676 }
5677 }
5678 }
5679 else if (VECTORP (spec))
5680 {
5681 ptrdiff_t i;
5682 for (i = 0; i < ASIZE (spec); ++i)
5683 {
5684 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5685 overlay, position, bufpos,
5686 replacing, frame_window_p,
5687 enable_eval);
5688 if (rv != 0)
5689 {
5690 replacing = rv;
5691
5692
5693 if (!it || STRINGP (object))
5694 break;
5695 }
5696 }
5697 }
5698 else
5699 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5700 bufpos, 0, frame_window_p,
5701 enable_eval);
5702 return replacing;
5703 }
5704
5705
5706
5707
5708 static struct text_pos
5709 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5710 {
5711 Lisp_Object end;
5712 struct text_pos end_pos;
5713
5714 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5715 Qdisplay, object, Qnil);
5716 CHARPOS (end_pos) = XFIXNAT (end);
5717 if (STRINGP (object))
5718 compute_string_pos (&end_pos, start_pos, it->string);
5719 else
5720 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5721
5722 return end_pos;
5723 }
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751 static int
5752 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5753 Lisp_Object overlay, struct text_pos *position,
5754 ptrdiff_t bufpos, int display_replaced,
5755 bool frame_window_p, bool enable_eval_p)
5756 {
5757 Lisp_Object form;
5758 Lisp_Object location, value;
5759 struct text_pos start_pos = *position;
5760 void *itdata = NULL;
5761
5762
5763
5764 form = Qt;
5765 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5766 {
5767 spec = XCDR (spec);
5768 if (!CONSP (spec))
5769 return 0;
5770 form = XCAR (spec);
5771 spec = XCDR (spec);
5772 }
5773
5774 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5775 form = Qnil;
5776 if (!NILP (form) && !EQ (form, Qt))
5777 {
5778 specpdl_ref count = SPECPDL_INDEX ();
5779
5780
5781
5782
5783
5784
5785 if (NILP (object))
5786 XSETBUFFER (object, current_buffer);
5787 specbind (Qobject, object);
5788 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5789 specbind (Qbuffer_position, make_fixnum (bufpos));
5790
5791
5792 itdata = bidi_shelve_cache ();
5793 form = safe_eval (form);
5794 bidi_unshelve_cache (itdata, false);
5795 form = unbind_to (count, form);
5796 }
5797
5798 if (NILP (form))
5799 return 0;
5800
5801
5802 if (CONSP (spec)
5803 && EQ (XCAR (spec), Qheight)
5804 && CONSP (XCDR (spec)))
5805 {
5806 if (it)
5807 {
5808 if (!FRAME_WINDOW_P (it->f))
5809 return 0;
5810
5811 it->font_height = XCAR (XCDR (spec));
5812 if (!NILP (it->font_height))
5813 {
5814 int new_height = -1;
5815
5816 if (CONSP (it->font_height)
5817 && (EQ (XCAR (it->font_height), Qplus)
5818 || EQ (XCAR (it->font_height), Qminus))
5819 && CONSP (XCDR (it->font_height))
5820 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5821 {
5822
5823 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5824 if (EQ (XCAR (it->font_height), Qplus))
5825 steps = - steps;
5826 it->face_id = smaller_face (it->f, it->face_id, steps);
5827 }
5828 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5829 {
5830
5831
5832 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5833 Lisp_Object height;
5834 itdata = bidi_shelve_cache ();
5835 height = safe_call1 (it->font_height,
5836 face->lface[LFACE_HEIGHT_INDEX]);
5837 bidi_unshelve_cache (itdata, false);
5838 if (NUMBERP (height))
5839 new_height = XFLOATINT (height);
5840 }
5841 else if (NUMBERP (it->font_height))
5842 {
5843
5844 struct face *f;
5845
5846 f = FACE_FROM_ID (it->f,
5847 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5848 new_height = (XFLOATINT (it->font_height)
5849 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5850 }
5851 else if (enable_eval_p)
5852 {
5853
5854
5855 specpdl_ref count = SPECPDL_INDEX ();
5856 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5857
5858 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5859 itdata = bidi_shelve_cache ();
5860 value = safe_eval (it->font_height);
5861 bidi_unshelve_cache (itdata, false);
5862 value = unbind_to (count, value);
5863
5864 if (NUMBERP (value))
5865 new_height = XFLOATINT (value);
5866 }
5867
5868 if (new_height > 0)
5869 it->face_id = face_with_height (it->f, it->face_id, new_height);
5870 }
5871 }
5872
5873 return 0;
5874 }
5875
5876
5877 if (CONSP (spec)
5878 && EQ (XCAR (spec), Qspace_width)
5879 && CONSP (XCDR (spec)))
5880 {
5881 if (it)
5882 {
5883 if (!FRAME_WINDOW_P (it->f))
5884 return 0;
5885
5886 value = XCAR (XCDR (spec));
5887 if (NUMBERP (value) && XFLOATINT (value) > 0)
5888 it->space_width = value;
5889 }
5890
5891 return 0;
5892 }
5893
5894
5895 if (CONSP (spec)
5896 && EQ (XCAR (spec), Qmin_width)
5897 && CONSP (XCDR (spec))
5898 && CONSP (XCAR (XCDR (spec))))
5899 {
5900 if (it)
5901 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5902 return 0;
5903 }
5904
5905
5906 if (CONSP (spec)
5907 && EQ (XCAR (spec), Qslice))
5908 {
5909 Lisp_Object tem;
5910
5911 if (it)
5912 {
5913 if (!FRAME_WINDOW_P (it->f))
5914 return 0;
5915
5916 if (tem = XCDR (spec), CONSP (tem))
5917 {
5918 it->slice.x = XCAR (tem);
5919 if (tem = XCDR (tem), CONSP (tem))
5920 {
5921 it->slice.y = XCAR (tem);
5922 if (tem = XCDR (tem), CONSP (tem))
5923 {
5924 it->slice.width = XCAR (tem);
5925 if (tem = XCDR (tem), CONSP (tem))
5926 it->slice.height = XCAR (tem);
5927 }
5928 }
5929 }
5930 }
5931
5932 return 0;
5933 }
5934
5935
5936 if (CONSP (spec)
5937 && EQ (XCAR (spec), Qraise)
5938 && CONSP (XCDR (spec)))
5939 {
5940 if (it)
5941 {
5942 if (!FRAME_WINDOW_P (it->f))
5943 return 0;
5944
5945 #ifdef HAVE_WINDOW_SYSTEM
5946 value = XCAR (XCDR (spec));
5947 if (NUMBERP (value))
5948 {
5949 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5950 it->voffset = - (XFLOATINT (value)
5951 * (normal_char_height (face->font, -1)));
5952 }
5953 #endif
5954 }
5955
5956 return 0;
5957 }
5958
5959
5960
5961 if (it && it->string_from_display_prop_p)
5962 return 0;
5963
5964
5965
5966 if (it)
5967 {
5968 start_pos = *position;
5969 *position = display_prop_end (it, object, start_pos);
5970
5971
5972
5973
5974
5975
5976
5977 if (!NILP (overlay))
5978 {
5979 ptrdiff_t ovendpos = OVERLAY_END (overlay);
5980
5981
5982
5983
5984
5985
5986
5987 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
5988
5989 if (ovendpos > CHARPOS (*position))
5990 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
5991 }
5992 }
5993 value = Qnil;
5994
5995
5996
5997 if (it)
5998 it->stop_charpos = position->charpos;
5999
6000
6001
6002 if (CONSP (spec)
6003 && (EQ (XCAR (spec), Qleft_fringe)
6004 || EQ (XCAR (spec), Qright_fringe))
6005 && CONSP (XCDR (spec)))
6006 {
6007 if (it)
6008 {
6009 if (!FRAME_WINDOW_P (it->f))
6010
6011
6012 {
6013
6014
6015
6016
6017 if (it->bidi_p)
6018 {
6019 it->position = *position;
6020 iterate_out_of_display_property (it);
6021 *position = it->position;
6022 }
6023 return 1;
6024 }
6025 }
6026 else if (!frame_window_p)
6027 return 1;
6028
6029 #ifdef HAVE_WINDOW_SYSTEM
6030 value = XCAR (XCDR (spec));
6031 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6032 if (! fringe_bitmap)
6033
6034
6035 {
6036 if (it && it->bidi_p)
6037 {
6038 it->position = *position;
6039 iterate_out_of_display_property (it);
6040 *position = it->position;
6041 }
6042 return 1;
6043 }
6044
6045 if (it)
6046 {
6047 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6048
6049 if (CONSP (XCDR (XCDR (spec))))
6050 {
6051 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6052 int face_id2;
6053
6054
6055
6056 specpdl_ref count1 = SPECPDL_INDEX ();
6057 specbind (Qinhibit_quit, Qt);
6058 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6059 FRINGE_FACE_ID, false);
6060 unbind_to (count1, Qnil);
6061 if (face_id2 >= 0)
6062 face_id = face_id2;
6063 }
6064
6065
6066
6067 push_it (it, position);
6068
6069 it->area = TEXT_AREA;
6070 it->what = IT_IMAGE;
6071 it->image_id = -1;
6072 it->position = start_pos;
6073 it->object = NILP (object) ? it->w->contents : object;
6074 it->method = GET_FROM_IMAGE;
6075 it->from_overlay = Qnil;
6076 it->face_id = face_id;
6077 it->from_disp_prop_p = true;
6078
6079
6080
6081
6082 *position = start_pos;
6083
6084 if (EQ (XCAR (spec), Qleft_fringe))
6085 {
6086 it->left_user_fringe_bitmap = fringe_bitmap;
6087 it->left_user_fringe_face_id = face_id;
6088 }
6089 else
6090 {
6091 it->right_user_fringe_bitmap = fringe_bitmap;
6092 it->right_user_fringe_face_id = face_id;
6093 }
6094 }
6095 #endif
6096 return 1;
6097 }
6098
6099
6100
6101
6102 location = Qunbound;
6103 if (CONSP (spec) && CONSP (XCAR (spec)))
6104 {
6105 Lisp_Object tem;
6106
6107 value = XCDR (spec);
6108 if (CONSP (value))
6109 value = XCAR (value);
6110
6111 tem = XCAR (spec);
6112 if (EQ (XCAR (tem), Qmargin)
6113 && (tem = XCDR (tem),
6114 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6115 (NILP (tem)
6116 || EQ (tem, Qleft_margin)
6117 || EQ (tem, Qright_margin))))
6118 location = tem;
6119 }
6120
6121 if (BASE_EQ (location, Qunbound))
6122 {
6123 location = Qnil;
6124 value = spec;
6125 }
6126
6127
6128
6129
6130
6131
6132
6133
6134 bool valid_p = (STRINGP (value)
6135 #ifdef HAVE_WINDOW_SYSTEM
6136 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6137 && valid_image_p (value))
6138 #endif
6139 || (CONSP (value) && EQ (XCAR (value), Qspace))
6140 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6141 && valid_xwidget_spec_p (value)));
6142
6143 if (valid_p && display_replaced == 0)
6144 {
6145 int retval = 1;
6146
6147 if (!it)
6148 {
6149
6150
6151
6152 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6153 retval = 2;
6154 return retval;
6155 }
6156
6157
6158
6159 push_it (it, position);
6160 it->from_overlay = overlay;
6161 it->from_disp_prop_p = true;
6162
6163 if (NILP (location))
6164 it->area = TEXT_AREA;
6165 else if (EQ (location, Qleft_margin))
6166 it->area = LEFT_MARGIN_AREA;
6167 else
6168 it->area = RIGHT_MARGIN_AREA;
6169
6170 if (STRINGP (value))
6171 {
6172 it->string = value;
6173 it->multibyte_p = STRING_MULTIBYTE (it->string);
6174 it->current.overlay_string_index = -1;
6175 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6176 it->end_charpos = it->string_nchars = SCHARS (it->string);
6177 it->method = GET_FROM_STRING;
6178 it->stop_charpos = 0;
6179 it->prev_stop = 0;
6180 it->base_level_stop = 0;
6181 it->string_from_display_prop_p = true;
6182 it->cmp_it.id = -1;
6183
6184
6185
6186 if (BUFFERP (object))
6187 *position = start_pos;
6188
6189
6190
6191
6192 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6193 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6194 else
6195 it->paragraph_embedding = L2R;
6196
6197
6198 if (it->bidi_p)
6199 {
6200 it->bidi_it.string.lstring = it->string;
6201 it->bidi_it.string.s = NULL;
6202 it->bidi_it.string.schars = it->end_charpos;
6203 it->bidi_it.string.bufpos = bufpos;
6204 it->bidi_it.string.from_disp_str = true;
6205 it->bidi_it.string.unibyte = !it->multibyte_p;
6206 it->bidi_it.w = it->w;
6207 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6208 }
6209 }
6210 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6211 {
6212 it->method = GET_FROM_STRETCH;
6213 it->object = value;
6214 *position = it->position = start_pos;
6215 retval = 1 + (it->area == TEXT_AREA);
6216 }
6217 else if (valid_xwidget_spec_p (value))
6218 {
6219 it->what = IT_XWIDGET;
6220 it->method = GET_FROM_XWIDGET;
6221 it->position = start_pos;
6222 it->object = NILP (object) ? it->w->contents : object;
6223 *position = start_pos;
6224 it->xwidget = lookup_xwidget (value);
6225 }
6226 #ifdef HAVE_WINDOW_SYSTEM
6227 else
6228 {
6229 specpdl_ref count = SPECPDL_INDEX ();
6230
6231 it->what = IT_IMAGE;
6232
6233
6234
6235 specbind (Qinhibit_quit, Qt);
6236 it->image_id = lookup_image (it->f, value, it->face_id);
6237 unbind_to (count, Qnil);
6238 it->position = start_pos;
6239 it->object = NILP (object) ? it->w->contents : object;
6240 it->method = GET_FROM_IMAGE;
6241
6242
6243
6244
6245 *position = start_pos;
6246 }
6247 #endif
6248
6249 return retval;
6250 }
6251
6252
6253
6254 *position = start_pos;
6255 return 0;
6256 }
6257
6258
6259
6260
6261
6262
6263 bool
6264 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6265 ptrdiff_t charpos, ptrdiff_t bytepos)
6266 {
6267 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6268 struct text_pos position;
6269
6270 SET_TEXT_POS (position, charpos, bytepos);
6271 return (handle_display_spec (NULL, prop, Qnil, overlay,
6272 &position, charpos, frame_window_p)
6273 != 0);
6274 }
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285 static bool
6286 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6287 {
6288 if (EQ (string, prop))
6289 return true;
6290
6291
6292 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6293 {
6294 prop = XCDR (prop);
6295 if (!CONSP (prop))
6296 return false;
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307 prop = XCDR (prop);
6308 }
6309
6310 if (CONSP (prop))
6311
6312 if (EQ (XCAR (prop), Qmargin))
6313 {
6314 prop = XCDR (prop);
6315 if (!CONSP (prop))
6316 return false;
6317
6318 prop = XCDR (prop);
6319 if (!CONSP (prop))
6320 return false;
6321 }
6322
6323 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6324 }
6325
6326
6327
6328
6329 static bool
6330 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6331 {
6332 if (CONSP (prop)
6333 && !EQ (XCAR (prop), Qwhen)
6334 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6335 {
6336
6337 while (CONSP (prop))
6338 {
6339 if (single_display_spec_string_p (XCAR (prop), string))
6340 return true;
6341 prop = XCDR (prop);
6342 }
6343 }
6344 else if (VECTORP (prop))
6345 {
6346
6347 ptrdiff_t i;
6348 for (i = 0; i < ASIZE (prop); ++i)
6349 if (single_display_spec_string_p (AREF (prop, i), string))
6350 return true;
6351 }
6352 else
6353 return single_display_spec_string_p (prop, string);
6354
6355 return false;
6356 }
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368 static ptrdiff_t
6369 string_buffer_position_lim (Lisp_Object string,
6370 ptrdiff_t from, ptrdiff_t to, bool back_p)
6371 {
6372 Lisp_Object limit, prop, pos;
6373 bool found = false;
6374
6375 pos = make_fixnum (max (from, BEGV));
6376
6377 if (!back_p)
6378 {
6379 limit = make_fixnum (min (to, ZV));
6380 while (!found && !EQ (pos, limit))
6381 {
6382 prop = Fget_char_property (pos, Qdisplay, Qnil);
6383 if (!NILP (prop) && display_prop_string_p (prop, string))
6384 found = true;
6385 else
6386 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6387 limit);
6388 }
6389 }
6390 else
6391 {
6392 limit = make_fixnum (max (to, BEGV));
6393 while (!found && !EQ (pos, limit))
6394 {
6395 prop = Fget_char_property (pos, Qdisplay, Qnil);
6396 if (!NILP (prop) && display_prop_string_p (prop, string))
6397 found = true;
6398 else
6399 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6400 limit);
6401 }
6402 }
6403
6404 return found ? XFIXNUM (pos) : 0;
6405 }
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416 static ptrdiff_t
6417 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6418 {
6419 const int MAX_DISTANCE = 1000;
6420 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6421 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6422 forward_limit, false);
6423
6424 if (!found)
6425 {
6426 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6427 found = string_buffer_position_lim (string, around_charpos,
6428 backward_limit, true);
6429 }
6430 return found;
6431 }
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442 static enum prop_handled
6443 handle_composition_prop (struct it *it)
6444 {
6445 Lisp_Object prop, string;
6446 ptrdiff_t pos, pos_byte, start, end;
6447
6448 if (STRINGP (it->string))
6449 {
6450 unsigned char *s;
6451
6452 pos = IT_STRING_CHARPOS (*it);
6453 pos_byte = IT_STRING_BYTEPOS (*it);
6454 string = it->string;
6455 s = SDATA (string) + pos_byte;
6456 if (STRING_MULTIBYTE (string))
6457 it->c = STRING_CHAR (s);
6458 else
6459 it->c = *s;
6460 }
6461 else
6462 {
6463 pos = IT_CHARPOS (*it);
6464 pos_byte = IT_BYTEPOS (*it);
6465 string = Qnil;
6466 it->c = FETCH_CHAR (pos_byte);
6467 }
6468
6469
6470
6471
6472 if (find_composition (pos, -1, &start, &end, &prop, string)
6473 && composition_valid_p (start, end, prop)
6474 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6475 {
6476 if (start < pos)
6477
6478
6479
6480 return HANDLED_NORMALLY;
6481 if (start != pos)
6482 {
6483 if (STRINGP (it->string))
6484 pos_byte = string_char_to_byte (it->string, start);
6485 else
6486 pos_byte = CHAR_TO_BYTE (start);
6487 }
6488 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6489 prop, string);
6490
6491 if (it->cmp_it.id >= 0)
6492 {
6493 it->cmp_it.ch = -1;
6494 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6495 it->cmp_it.nglyphs = -1;
6496 }
6497 }
6498
6499 return HANDLED_NORMALLY;
6500 }
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511 struct overlay_entry
6512 {
6513 Lisp_Object overlay;
6514 Lisp_Object string;
6515 EMACS_INT priority;
6516 bool after_string_p;
6517 };
6518
6519
6520
6521
6522
6523 static enum prop_handled
6524 handle_overlay_change (struct it *it)
6525 {
6526 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6527 return HANDLED_RECOMPUTE_PROPS;
6528 else
6529 return HANDLED_NORMALLY;
6530 }
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540 static void
6541 next_overlay_string (struct it *it)
6542 {
6543 ++it->current.overlay_string_index;
6544 if (it->current.overlay_string_index == it->n_overlay_strings)
6545 {
6546
6547
6548
6549
6550 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6551 pop_it (it);
6552 eassert (it->sp > 0
6553 || (NILP (it->string)
6554 && it->method == GET_FROM_BUFFER
6555 && it->stop_charpos >= BEGV
6556 && it->stop_charpos <= it->end_charpos));
6557 it->current.overlay_string_index = -1;
6558 it->n_overlay_strings = 0;
6559
6560
6561
6562
6563 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6564 pop_it (it);
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6575 it->ignore_overlay_strings_at_pos_p = true;
6576
6577
6578
6579
6580 if (NILP (it->string)
6581 && IT_CHARPOS (*it) >= it->end_charpos
6582 && it->overlay_strings_charpos >= it->end_charpos)
6583 it->overlay_strings_at_end_processed_p = true;
6584
6585
6586
6587
6588
6589
6590
6591 it->overlay_strings_charpos = -1;
6592 }
6593 else
6594 {
6595
6596
6597
6598
6599
6600
6601 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6602
6603 if (it->current.overlay_string_index && i == 0)
6604 load_overlay_strings (it, it->overlay_strings_charpos);
6605
6606
6607
6608 it->string = it->overlay_strings[i];
6609 it->multibyte_p = STRING_MULTIBYTE (it->string);
6610 SET_TEXT_POS (it->current.string_pos, 0, 0);
6611 it->method = GET_FROM_STRING;
6612 it->stop_charpos = 0;
6613 it->end_charpos = SCHARS (it->string);
6614 if (it->cmp_it.stop_pos >= 0)
6615 it->cmp_it.stop_pos = 0;
6616 it->prev_stop = 0;
6617 it->base_level_stop = 0;
6618
6619
6620 if (it->bidi_p)
6621 {
6622 it->bidi_it.string.lstring = it->string;
6623 it->bidi_it.string.s = NULL;
6624 it->bidi_it.string.schars = SCHARS (it->string);
6625 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6626 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6627 it->bidi_it.string.unibyte = !it->multibyte_p;
6628 it->bidi_it.w = it->w;
6629 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6630 }
6631 }
6632
6633 CHECK_IT (it);
6634 }
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653 static int
6654 compare_overlay_entries (const void *e1, const void *e2)
6655 {
6656 struct overlay_entry const *entry1 = e1;
6657 struct overlay_entry const *entry2 = e2;
6658 int result;
6659
6660 if (entry1->after_string_p != entry2->after_string_p)
6661 {
6662
6663
6664 if (EQ (entry1->overlay, entry2->overlay))
6665 result = entry1->after_string_p ? 1 : -1;
6666 else
6667 result = entry1->after_string_p ? -1 : 1;
6668 }
6669 else if (entry1->priority != entry2->priority)
6670 {
6671 if (entry1->after_string_p)
6672
6673 result = entry2->priority < entry1->priority ? -1 : 1;
6674 else
6675
6676 result = entry1->priority < entry2->priority ? -1 : 1;
6677 }
6678 else
6679 result = 0;
6680
6681 return result;
6682 }
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709 static void
6710 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6711 {
6712 ptrdiff_t n = 0;
6713 struct overlay_entry entriesbuf[20];
6714 ptrdiff_t size = ARRAYELTS (entriesbuf);
6715 struct overlay_entry *entries = entriesbuf;
6716 struct itree_node *node;
6717
6718 USE_SAFE_ALLOCA;
6719
6720 if (charpos <= 0)
6721 charpos = IT_CHARPOS (*it);
6722
6723
6724
6725
6726
6727 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6728 do \
6729 { \
6730 Lisp_Object priority; \
6731 \
6732 if (n == size) \
6733 { \
6734 struct overlay_entry *old = entries; \
6735 SAFE_NALLOCA (entries, 2, size); \
6736 memcpy (entries, old, size * sizeof *entries); \
6737 size *= 2; \
6738 } \
6739 \
6740 entries[n].string = (STRING); \
6741 entries[n].overlay = (OVERLAY); \
6742 priority = Foverlay_get ((OVERLAY), Qpriority); \
6743 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6744 entries[n].after_string_p = (AFTER_P); \
6745 ++n; \
6746 } \
6747 while (false)
6748
6749
6750
6751 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6752 {
6753 Lisp_Object overlay = node->data;
6754 eassert (OVERLAYP (overlay));
6755 ptrdiff_t start = node->begin;
6756 ptrdiff_t end = node->end;
6757
6758
6759
6760 if (end != charpos && start != charpos)
6761 continue;
6762
6763
6764 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6765 if (WINDOWP (window) && XWINDOW (window) != it->w)
6766 continue;
6767
6768
6769
6770
6771 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6772 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6773
6774
6775 Lisp_Object str;
6776 if ((start == charpos || (end == charpos && invis != 0))
6777 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6778 && SCHARS (str))
6779 RECORD_OVERLAY_STRING (overlay, str, false);
6780
6781
6782 if ((end == charpos || (start == charpos && invis != 0))
6783 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6784 && SCHARS (str))
6785 RECORD_OVERLAY_STRING (overlay, str, true);
6786 }
6787
6788 #undef RECORD_OVERLAY_STRING
6789
6790
6791 if (n > 1)
6792 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6793
6794
6795 it->n_overlay_strings = n;
6796 it->overlay_strings_charpos = charpos;
6797
6798
6799
6800
6801 ptrdiff_t j = it->current.overlay_string_index;
6802 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6803 {
6804 it->overlay_strings[i] = entries[j].string;
6805 it->string_overlays[i] = entries[j].overlay;
6806 }
6807
6808 CHECK_IT (it);
6809 SAFE_FREE ();
6810 }
6811
6812
6813
6814
6815
6816
6817 static bool
6818 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6819 {
6820
6821
6822
6823
6824
6825
6826
6827 it->current.overlay_string_index = 0;
6828 load_overlay_strings (it, charpos);
6829
6830
6831
6832
6833 if (it->n_overlay_strings)
6834 {
6835
6836
6837
6838 if (compute_stop_p)
6839 compute_stop_pos (it);
6840 eassert (it->face_id >= 0);
6841
6842
6843
6844 eassert (!compute_stop_p || it->sp == 0);
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854 if (!(!it->bidi_p
6855 && STRINGP (it->string) && !SCHARS (it->string)))
6856 push_it (it, NULL);
6857
6858
6859
6860 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6861 it->string = it->overlay_strings[0];
6862 it->from_overlay = Qnil;
6863 it->stop_charpos = 0;
6864 eassert (STRINGP (it->string));
6865 it->end_charpos = SCHARS (it->string);
6866 it->prev_stop = 0;
6867 it->base_level_stop = 0;
6868 it->multibyte_p = STRING_MULTIBYTE (it->string);
6869 it->method = GET_FROM_STRING;
6870 it->from_disp_prop_p = 0;
6871 it->cmp_it.id = -1;
6872
6873
6874
6875 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6876 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6877 else
6878 it->paragraph_embedding = L2R;
6879
6880
6881 if (it->bidi_p)
6882 {
6883 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6884
6885 it->bidi_it.string.lstring = it->string;
6886 it->bidi_it.string.s = NULL;
6887 it->bidi_it.string.schars = SCHARS (it->string);
6888 it->bidi_it.string.bufpos = pos;
6889 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6890 it->bidi_it.string.unibyte = !it->multibyte_p;
6891 it->bidi_it.w = it->w;
6892 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6893 }
6894 return true;
6895 }
6896
6897 it->current.overlay_string_index = -1;
6898 return false;
6899 }
6900
6901 static bool
6902 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6903 {
6904 it->string = Qnil;
6905 it->method = GET_FROM_BUFFER;
6906
6907 get_overlay_strings_1 (it, charpos, true);
6908
6909 CHECK_IT (it);
6910
6911
6912 return STRINGP (it->string);
6913 }
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927 static void
6928 push_it (struct it *it, struct text_pos *position)
6929 {
6930 struct iterator_stack_entry *p;
6931
6932 eassert (it->sp < IT_STACK_SIZE);
6933 p = it->stack + it->sp;
6934
6935 p->stop_charpos = it->stop_charpos;
6936 p->prev_stop = it->prev_stop;
6937 p->base_level_stop = it->base_level_stop;
6938 p->cmp_it = it->cmp_it;
6939 eassert (it->face_id >= 0);
6940 p->face_id = it->face_id;
6941 p->string = it->string;
6942 p->method = it->method;
6943 p->from_overlay = it->from_overlay;
6944 switch (p->method)
6945 {
6946 case GET_FROM_IMAGE:
6947 p->u.image.object = it->object;
6948 p->u.image.image_id = it->image_id;
6949 p->u.image.slice = it->slice;
6950 break;
6951 case GET_FROM_STRETCH:
6952 p->u.stretch.object = it->object;
6953 break;
6954 case GET_FROM_XWIDGET:
6955 p->u.xwidget.object = it->object;
6956 break;
6957 case GET_FROM_BUFFER:
6958 case GET_FROM_DISPLAY_VECTOR:
6959 case GET_FROM_STRING:
6960 case GET_FROM_C_STRING:
6961 break;
6962 default:
6963 emacs_abort ();
6964 }
6965 p->position = position ? *position : it->position;
6966 p->current = it->current;
6967 p->end_charpos = it->end_charpos;
6968 p->string_nchars = it->string_nchars;
6969 p->area = it->area;
6970 p->multibyte_p = it->multibyte_p;
6971 p->avoid_cursor_p = it->avoid_cursor_p;
6972 p->space_width = it->space_width;
6973 p->font_height = it->font_height;
6974 p->voffset = it->voffset;
6975 p->string_from_display_prop_p = it->string_from_display_prop_p;
6976 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
6977 p->display_ellipsis_p = false;
6978 p->line_wrap = it->line_wrap;
6979 p->bidi_p = it->bidi_p;
6980 p->paragraph_embedding = it->paragraph_embedding;
6981 p->from_disp_prop_p = it->from_disp_prop_p;
6982 ++it->sp;
6983
6984
6985 if (it->bidi_p)
6986 bidi_push_it (&it->bidi_it);
6987 }
6988
6989 static void
6990 iterate_out_of_display_property (struct it *it)
6991 {
6992 bool buffer_p = !STRINGP (it->string);
6993 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
6994 ptrdiff_t bob = (buffer_p ? BEGV : 0);
6995
6996 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
6997
6998
6999
7000
7001 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
7002 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
7003
7004 while (it->bidi_it.charpos >= bob
7005 && it->prev_stop <= it->bidi_it.charpos
7006 && it->bidi_it.charpos < CHARPOS (it->position)
7007 && it->bidi_it.charpos < eob)
7008 bidi_move_to_visually_next (&it->bidi_it);
7009
7010
7011 if (it->bidi_it.charpos > CHARPOS (it->position))
7012 it->prev_stop = CHARPOS (it->position);
7013
7014
7015 if (it->bidi_it.charpos != CHARPOS (it->position))
7016 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7017 if (buffer_p)
7018 it->current.pos = it->position;
7019 else
7020 it->current.string_pos = it->position;
7021 }
7022
7023
7024
7025
7026
7027 static void
7028 restore_face_box_flags (struct it *it, int prev_face_id)
7029 {
7030 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7031
7032 if (face)
7033 {
7034 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7035
7036 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7037 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7038 && (prev_face == NULL
7039 || prev_face->box == FACE_NO_BOX));
7040 it->face_box_p = face->box != FACE_NO_BOX;
7041 }
7042 }
7043
7044
7045
7046
7047
7048
7049
7050 static void
7051 pop_it (struct it *it)
7052 {
7053 struct iterator_stack_entry *p;
7054 bool from_display_prop = it->from_disp_prop_p;
7055 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7056 int prev_face_id = it->face_id;
7057
7058 eassert (it->sp > 0);
7059 --it->sp;
7060 p = it->stack + it->sp;
7061 it->stop_charpos = p->stop_charpos;
7062 it->prev_stop = p->prev_stop;
7063 it->base_level_stop = p->base_level_stop;
7064 it->cmp_it = p->cmp_it;
7065 it->face_id = p->face_id;
7066 it->current = p->current;
7067 it->position = p->position;
7068 it->string = p->string;
7069 it->from_overlay = p->from_overlay;
7070 if (NILP (it->string))
7071 SET_TEXT_POS (it->current.string_pos, -1, -1);
7072 it->method = p->method;
7073 switch (it->method)
7074 {
7075 case GET_FROM_IMAGE:
7076 it->image_id = p->u.image.image_id;
7077 it->object = p->u.image.object;
7078 it->slice = p->u.image.slice;
7079 break;
7080 case GET_FROM_XWIDGET:
7081 it->object = p->u.xwidget.object;
7082 break;
7083 case GET_FROM_STRETCH:
7084 it->object = p->u.stretch.object;
7085 break;
7086 case GET_FROM_BUFFER:
7087 {
7088 restore_face_box_flags (it, prev_face_id);
7089 it->object = it->w->contents;
7090 }
7091 break;
7092 case GET_FROM_STRING:
7093 {
7094 restore_face_box_flags (it, prev_face_id);
7095 it->object = it->string;
7096 }
7097 break;
7098 case GET_FROM_DISPLAY_VECTOR:
7099 if (it->s)
7100 it->method = GET_FROM_C_STRING;
7101 else if (STRINGP (it->string))
7102 it->method = GET_FROM_STRING;
7103 else
7104 {
7105 it->method = GET_FROM_BUFFER;
7106 it->object = it->w->contents;
7107 }
7108 break;
7109 case GET_FROM_C_STRING:
7110 break;
7111 default:
7112 emacs_abort ();
7113 }
7114 it->end_charpos = p->end_charpos;
7115 it->string_nchars = p->string_nchars;
7116 it->area = p->area;
7117 it->multibyte_p = p->multibyte_p;
7118 it->avoid_cursor_p = p->avoid_cursor_p;
7119 it->space_width = p->space_width;
7120 it->font_height = p->font_height;
7121 it->voffset = p->voffset;
7122 it->string_from_display_prop_p = p->string_from_display_prop_p;
7123 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7124 it->line_wrap = p->line_wrap;
7125 it->bidi_p = p->bidi_p;
7126 it->paragraph_embedding = p->paragraph_embedding;
7127 it->from_disp_prop_p = p->from_disp_prop_p;
7128 if (it->bidi_p)
7129 {
7130 bidi_pop_it (&it->bidi_it);
7131
7132
7133
7134
7135
7136
7137
7138 if (from_display_prop
7139 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7140 iterate_out_of_display_property (it);
7141
7142 eassert ((BUFFERP (it->object)
7143 && IT_CHARPOS (*it) == it->bidi_it.charpos
7144 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7145 || (STRINGP (it->object)
7146 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7147 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7148 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7149
7150
7151
7152
7153
7154
7155 || it->sp > 0);
7156 }
7157
7158
7159
7160 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7161 it->ignore_overlay_strings_at_pos_p = false;
7162 }
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172 static void
7173 back_to_previous_line_start (struct it *it)
7174 {
7175 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7176
7177 dec_both (&cp, &bp);
7178 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7179 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7180 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7181 }
7182
7183
7184
7185
7186
7187 static bool
7188 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7189 {
7190 struct itree_node *node;
7191
7192 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7193 {
7194 Lisp_Object overlay = node->data;
7195 eassert (OVERLAYP (overlay));
7196
7197
7198 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7199 if (WINDOWP (window) && XWINDOW (window) != w)
7200 continue;
7201
7202 ptrdiff_t ostart = node->begin;
7203 ptrdiff_t oend = node->end;
7204
7205
7206 if (!((startpos < oend && ostart < endpos)
7207 || (ostart == oend
7208 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7209 continue;
7210
7211 Lisp_Object str;
7212 str = Foverlay_get (overlay, Qbefore_string);
7213 if (STRINGP (str) && SCHARS (str)
7214 && memchr (SDATA (str), '\n', SBYTES (str)))
7215 return true;
7216 str = Foverlay_get (overlay, Qafter_string);
7217 if (STRINGP (str) && SCHARS (str)
7218 && memchr (SDATA (str), '\n', SBYTES (str)))
7219 return true;
7220 }
7221
7222
7223 Lisp_Object cpos = make_fixnum (startpos);
7224 Lisp_Object limpos = make_fixnum (endpos);
7225
7226 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7227 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7228 {
7229 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7230 Lisp_Object string = string_from_display_spec (spec);
7231 if (STRINGP (string)
7232 && memchr (SDATA (string), '\n', SBYTES (string)))
7233 return true;
7234 }
7235
7236 return false;
7237 }
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261 static bool
7262 forward_to_next_line_start (struct it *it, bool *skipped_p,
7263 struct bidi_it *bidi_it_prev)
7264 {
7265 ptrdiff_t old_selective;
7266 bool newline_found_p = false;
7267 int n;
7268 const int MAX_NEWLINE_DISTANCE = 500;
7269
7270
7271
7272 if (it->what == IT_CHARACTER
7273 && it->c == '\n'
7274 && CHARPOS (it->position) == IT_CHARPOS (*it))
7275 {
7276 if (it->bidi_p && bidi_it_prev)
7277 *bidi_it_prev = it->bidi_it;
7278 set_iterator_to_next (it, false);
7279 it->c = 0;
7280 return true;
7281 }
7282
7283
7284
7285
7286
7287 old_selective = it->selective;
7288 it->selective = 0;
7289
7290
7291
7292
7293 for (n = 0;
7294 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7295 n += !STRINGP (it->string))
7296 {
7297 if (!get_next_display_element (it))
7298 return false;
7299 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7300 if (newline_found_p && it->bidi_p && bidi_it_prev)
7301 *bidi_it_prev = it->bidi_it;
7302 set_iterator_to_next (it, false);
7303 }
7304
7305
7306
7307 if (!newline_found_p)
7308 {
7309 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7310 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7311 1, &bytepos);
7312 eassert (!STRINGP (it->string));
7313
7314
7315
7316
7317 bool no_strings_with_newlines = it->stop_charpos >= limit;
7318
7319 if (!no_strings_with_newlines)
7320 {
7321 if (!(current_buffer->long_line_optimizations_p
7322 && it->line_wrap == TRUNCATE))
7323 {
7324
7325
7326 Lisp_Object pos =
7327 Fnext_single_property_change (make_fixnum (start),
7328 Qdisplay, Qnil,
7329 make_fixnum (limit));
7330 no_strings_with_newlines =
7331 (NILP (pos) || XFIXNAT (pos) == limit)
7332 && next_overlay_change (start) == ZV;
7333 }
7334 else
7335 {
7336
7337
7338
7339
7340 no_strings_with_newlines =
7341 !strings_with_newlines (start, limit, it->w);
7342 }
7343 }
7344
7345
7346
7347
7348 if (no_strings_with_newlines)
7349 {
7350 if (!it->bidi_p || !bidi_it_prev)
7351 {
7352
7353 IT_CHARPOS (*it) = limit;
7354 IT_BYTEPOS (*it) = bytepos;
7355 }
7356 else
7357 {
7358
7359
7360
7361 struct bidi_it bprev;
7362
7363
7364
7365
7366 if (it->bidi_it.disp_pos < limit)
7367 {
7368 it->bidi_it.disp_pos = limit;
7369 it->bidi_it.disp_prop = 0;
7370 }
7371 do {
7372 bprev = it->bidi_it;
7373 bidi_move_to_visually_next (&it->bidi_it);
7374 } while (it->bidi_it.charpos != limit);
7375 IT_CHARPOS (*it) = limit;
7376 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7377 if (bidi_it_prev)
7378 *bidi_it_prev = bprev;
7379 }
7380 *skipped_p = newline_found_p = true;
7381 }
7382 else
7383 {
7384
7385 while (!newline_found_p)
7386 {
7387 if (!get_next_display_element (it))
7388 break;
7389 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7390 if (newline_found_p && it->bidi_p && bidi_it_prev)
7391 *bidi_it_prev = it->bidi_it;
7392 set_iterator_to_next (it, false);
7393 }
7394 }
7395 }
7396
7397 it->selective = old_selective;
7398 return newline_found_p;
7399 }
7400
7401
7402
7403
7404
7405
7406
7407 static void
7408 back_to_previous_visible_line_start (struct it *it)
7409 {
7410 while (IT_CHARPOS (*it) > BEGV)
7411 {
7412 back_to_previous_line_start (it);
7413
7414 if (IT_CHARPOS (*it) <= BEGV)
7415 break;
7416
7417
7418
7419 if (it->selective > 0
7420 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7421 it->selective))
7422 continue;
7423
7424
7425 {
7426 Lisp_Object prop;
7427 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7428 Qinvisible, it->window);
7429 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7430 continue;
7431 }
7432
7433 if (IT_CHARPOS (*it) <= BEGV)
7434 break;
7435
7436 {
7437 struct it it2;
7438 void *it2data = NULL;
7439 ptrdiff_t pos;
7440 ptrdiff_t beg, end;
7441 Lisp_Object val, overlay;
7442
7443 SAVE_IT (it2, *it, it2data);
7444
7445
7446 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7447 && beg < IT_CHARPOS (*it))
7448 goto replaced;
7449
7450
7451
7452 pos = --IT_CHARPOS (it2);
7453 --IT_BYTEPOS (it2);
7454 it2.sp = 0;
7455 bidi_unshelve_cache (NULL, false);
7456 it2.string_from_display_prop_p = false;
7457 it2.from_disp_prop_p = false;
7458 if (handle_display_prop (&it2) == HANDLED_RETURN
7459 && !NILP (val = get_char_property_and_overlay
7460 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7461 && (OVERLAYP (overlay)
7462 ? (beg = OVERLAY_START (overlay))
7463 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7464 {
7465 RESTORE_IT (it, it, it2data);
7466 goto replaced;
7467 }
7468
7469
7470 RESTORE_IT (it, it, it2data);
7471 break;
7472
7473 replaced:
7474 if (beg < BEGV)
7475 beg = BEGV;
7476 IT_CHARPOS (*it) = beg;
7477 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7478 }
7479 }
7480
7481 it->continuation_lines_width = 0;
7482
7483 eassert (IT_CHARPOS (*it) >= BEGV);
7484 eassert (it->medium_narrowing_begv > 0
7485 || IT_CHARPOS (*it) == BEGV
7486 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7487 CHECK_IT (it);
7488 }
7489
7490
7491
7492
7493
7494
7495
7496 void
7497 reseat_at_previous_visible_line_start (struct it *it)
7498 {
7499 back_to_previous_visible_line_start (it);
7500 reseat (it, it->current.pos, true);
7501 CHECK_IT (it);
7502 }
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512 static void
7513 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7514 {
7515 bool skipped_p = false;
7516 struct bidi_it bidi_it_prev;
7517 bool newline_found_p
7518 = forward_to_next_line_start (it, &skipped_p,
7519 on_newline_p ? &bidi_it_prev : NULL);
7520
7521
7522
7523 if (it->selective > 0)
7524 while (IT_CHARPOS (*it) < ZV
7525 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7526 it->selective))
7527 {
7528 eassert (IT_BYTEPOS (*it) == BEGV
7529 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7530 newline_found_p =
7531 forward_to_next_line_start (it, &skipped_p,
7532 on_newline_p ? &bidi_it_prev : NULL);
7533 }
7534
7535
7536 if (on_newline_p && newline_found_p)
7537 {
7538 if (STRINGP (it->string))
7539 {
7540 if (IT_STRING_CHARPOS (*it) > 0)
7541 {
7542 if (!it->bidi_p)
7543 {
7544 --IT_STRING_CHARPOS (*it);
7545 --IT_STRING_BYTEPOS (*it);
7546 }
7547 else
7548 {
7549
7550
7551
7552 it->bidi_it = bidi_it_prev;
7553 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7554 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7555 }
7556 }
7557 }
7558 else if (IT_CHARPOS (*it) > BEGV)
7559 {
7560 if (!it->bidi_p)
7561 {
7562 --IT_CHARPOS (*it);
7563 --IT_BYTEPOS (*it);
7564 }
7565 else
7566 {
7567
7568
7569 it->bidi_it = bidi_it_prev;
7570 IT_CHARPOS (*it) = it->bidi_it.charpos;
7571 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7572 }
7573 reseat (it, it->current.pos, false);
7574 }
7575 }
7576 else if (skipped_p)
7577 reseat (it, it->current.pos, false);
7578
7579 CHECK_IT (it);
7580 }
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593 static void
7594 reseat (struct it *it, struct text_pos pos, bool force_p)
7595 {
7596 ptrdiff_t original_pos = IT_CHARPOS (*it);
7597
7598 reseat_1 (it, pos, false);
7599
7600 if (current_buffer->long_line_optimizations_p)
7601 {
7602 if (!it->medium_narrowing_begv)
7603 {
7604 it->medium_narrowing_begv
7605 = get_medium_narrowing_begv (it->w, window_point (it->w));
7606 it->medium_narrowing_zv
7607 = get_medium_narrowing_zv (it->w, window_point (it->w));
7608 it->large_narrowing_begv
7609 = get_large_narrowing_begv (window_point (it->w));
7610 it->large_narrowing_zv
7611 = get_large_narrowing_zv (window_point (it->w));
7612 }
7613 else if ((pos.charpos < it->medium_narrowing_begv
7614 || pos.charpos > it->medium_narrowing_zv)
7615 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7616 {
7617 it->medium_narrowing_begv
7618 = get_medium_narrowing_begv (it->w, pos.charpos);
7619 it->medium_narrowing_zv
7620 = get_medium_narrowing_zv (it->w, pos.charpos);
7621 it->large_narrowing_begv
7622 = get_large_narrowing_begv (window_point (it->w));
7623 it->large_narrowing_zv
7624 = get_large_narrowing_zv (window_point (it->w));
7625 }
7626 }
7627
7628
7629
7630 if (force_p
7631 || CHARPOS (pos) > it->stop_charpos
7632 || CHARPOS (pos) < original_pos)
7633 {
7634 if (it->bidi_p)
7635 {
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646 if (CHARPOS (pos) != it->prev_stop)
7647 it->prev_stop = CHARPOS (pos);
7648 if (CHARPOS (pos) < it->base_level_stop)
7649 it->base_level_stop = 0;
7650 handle_stop (it);
7651 }
7652 else
7653 {
7654 handle_stop (it);
7655 it->prev_stop = it->base_level_stop = 0;
7656 }
7657
7658 }
7659
7660 CHECK_IT (it);
7661 }
7662
7663
7664
7665
7666
7667 static void
7668 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7669 {
7670
7671 eassert (it->s == NULL);
7672
7673
7674 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7675
7676 it->current.pos = it->position = pos;
7677 it->end_charpos = ZV;
7678 it->dpvec = NULL;
7679 it->current.dpvec_index = -1;
7680 it->current.overlay_string_index = -1;
7681 IT_STRING_CHARPOS (*it) = -1;
7682 IT_STRING_BYTEPOS (*it) = -1;
7683 it->string = Qnil;
7684 it->method = GET_FROM_BUFFER;
7685 it->object = it->w->contents;
7686 it->area = TEXT_AREA;
7687 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7688 it->sp = 0;
7689 it->string_from_display_prop_p = false;
7690 it->string_from_prefix_prop_p = false;
7691
7692 it->from_disp_prop_p = false;
7693 it->face_before_selective_p = false;
7694 if (it->bidi_p)
7695 {
7696 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7697 &it->bidi_it);
7698 bidi_unshelve_cache (NULL, false);
7699 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7700 it->bidi_it.string.s = NULL;
7701 it->bidi_it.string.lstring = Qnil;
7702 it->bidi_it.string.bufpos = 0;
7703 it->bidi_it.string.from_disp_str = false;
7704 it->bidi_it.string.unibyte = false;
7705 it->bidi_it.w = it->w;
7706 }
7707
7708 if (set_stop_p)
7709 {
7710 it->stop_charpos = CHARPOS (pos);
7711 it->base_level_stop = CHARPOS (pos);
7712 }
7713
7714 it->cmp_it.id = -1;
7715 it->min_width_property = Qnil;
7716 }
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737 static void
7738 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7739 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7740 int multibyte)
7741 {
7742
7743 it->stop_charpos = -1;
7744
7745
7746 memset (&it->current, 0, sizeof it->current);
7747 it->current.overlay_string_index = -1;
7748 it->current.dpvec_index = -1;
7749 eassert (charpos >= 0);
7750
7751
7752
7753 if (multibyte >= 0)
7754 it->multibyte_p = multibyte > 0;
7755
7756
7757
7758
7759
7760 it->bidi_p =
7761 !redisplay__inhibit_bidi
7762 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7763
7764 if (s == NULL)
7765 {
7766 eassert (STRINGP (string));
7767 it->string = string;
7768 it->s = NULL;
7769 it->end_charpos = it->string_nchars = SCHARS (string);
7770 it->method = GET_FROM_STRING;
7771 it->current.string_pos = string_pos (charpos, string);
7772
7773 if (it->bidi_p)
7774 {
7775 it->bidi_it.string.lstring = string;
7776 it->bidi_it.string.s = NULL;
7777 it->bidi_it.string.schars = it->end_charpos;
7778 it->bidi_it.string.bufpos = 0;
7779 it->bidi_it.string.from_disp_str = false;
7780 it->bidi_it.string.unibyte = !it->multibyte_p;
7781 it->bidi_it.w = it->w;
7782 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7783 FRAME_WINDOW_P (it->f), &it->bidi_it);
7784 }
7785 }
7786 else
7787 {
7788 it->s = (const unsigned char *) s;
7789 it->string = Qnil;
7790
7791
7792
7793 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7794 if (it->multibyte_p)
7795 {
7796 it->current.pos = c_string_pos (charpos, s, true);
7797 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7798 }
7799 else
7800 {
7801 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7802 it->end_charpos = it->string_nchars = strlen (s);
7803 }
7804
7805 if (it->bidi_p)
7806 {
7807 it->bidi_it.string.lstring = Qnil;
7808 it->bidi_it.string.s = (const unsigned char *) s;
7809 it->bidi_it.string.schars = it->end_charpos;
7810 it->bidi_it.string.bufpos = 0;
7811 it->bidi_it.string.from_disp_str = false;
7812 it->bidi_it.string.unibyte = !it->multibyte_p;
7813 it->bidi_it.w = it->w;
7814 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7815 &it->bidi_it);
7816 }
7817 it->method = GET_FROM_C_STRING;
7818 }
7819
7820
7821
7822 if (precision > 0 && it->end_charpos - charpos > precision)
7823 {
7824 it->end_charpos = it->string_nchars = charpos + precision;
7825 if (it->bidi_p)
7826 it->bidi_it.string.schars = it->end_charpos;
7827 }
7828
7829
7830
7831
7832
7833 if (field_width < 0)
7834 field_width = DISP_INFINITY;
7835
7836
7837
7838 if (field_width > it->end_charpos - charpos)
7839 it->end_charpos = charpos + field_width;
7840
7841
7842 if (DISP_TABLE_P (Vstandard_display_table))
7843 it->dp = XCHAR_TABLE (Vstandard_display_table);
7844
7845 it->stop_charpos = charpos;
7846 it->prev_stop = charpos;
7847 it->base_level_stop = 0;
7848 if (it->bidi_p)
7849 {
7850 it->bidi_it.first_elt = true;
7851 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7852 it->bidi_it.disp_pos = -1;
7853 }
7854 if (s == NULL && it->multibyte_p)
7855 {
7856 ptrdiff_t endpos = SCHARS (it->string);
7857 if (endpos > it->end_charpos)
7858 endpos = it->end_charpos;
7859 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7860 it->string, true);
7861 }
7862 CHECK_IT (it);
7863 }
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873 typedef bool (*next_element_function) (struct it *);
7874
7875 static next_element_function const get_next_element[NUM_IT_METHODS] =
7876 {
7877 next_element_from_buffer,
7878 next_element_from_display_vector,
7879 next_element_from_string,
7880 next_element_from_c_string,
7881 next_element_from_image,
7882 next_element_from_stretch,
7883 next_element_from_xwidget,
7884 };
7885
7886 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7898 ((IT)->cmp_it.id >= 0 \
7899 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7900 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7901 END_CHARPOS, (IT)->w, \
7902 (IT)->bidi_p \
7903 ? (IT)->bidi_it.resolved_level \
7904 : -1, \
7905 FACE_FROM_ID_OR_NULL ((IT)->f, \
7906 (IT)->face_id), \
7907 (IT)->string)))
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917 Lisp_Object
7918 lookup_glyphless_char_display (int c, struct it *it)
7919 {
7920 Lisp_Object glyphless_method = Qnil;
7921
7922 if (CHAR_TABLE_P (Vglyphless_char_display)
7923 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7924 {
7925 if (c >= 0)
7926 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7927 else
7928 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7929
7930 if (CONSP (glyphless_method))
7931 glyphless_method = FRAME_WINDOW_P (it->f)
7932 ? XCAR (glyphless_method)
7933 : XCDR (glyphless_method);
7934 }
7935
7936 retry:
7937 if (NILP (glyphless_method))
7938 {
7939 if (c >= 0)
7940
7941 return Qnil;
7942
7943 glyphless_method = Qempty_box;
7944 }
7945 if (EQ (glyphless_method, Qzero_width))
7946 {
7947 if (c >= 0)
7948 return glyphless_method;
7949
7950 glyphless_method = Qempty_box;
7951 }
7952 if (EQ (glyphless_method, Qthin_space))
7953 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7954 else if (EQ (glyphless_method, Qempty_box))
7955 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7956 else if (EQ (glyphless_method, Qhex_code))
7957 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7958 else if (STRINGP (glyphless_method))
7959 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7960 else
7961 {
7962
7963 glyphless_method = Qnil;
7964 goto retry;
7965 }
7966 it->what = IT_GLYPHLESS;
7967 return glyphless_method;
7968 }
7969
7970
7971
7972 static struct frame *last_escape_glyph_frame = NULL;
7973 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
7974 static int last_escape_glyph_merged_face_id = 0;
7975
7976 static int
7977 merge_escape_glyph_face (struct it *it)
7978 {
7979 int face_id;
7980
7981 if (it->f == last_escape_glyph_frame
7982 && it->face_id == last_escape_glyph_face_id)
7983 face_id = last_escape_glyph_merged_face_id;
7984 else
7985 {
7986
7987 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
7988 last_escape_glyph_frame = it->f;
7989 last_escape_glyph_face_id = it->face_id;
7990 last_escape_glyph_merged_face_id = face_id;
7991 }
7992 return face_id;
7993 }
7994
7995
7996
7997 static struct frame *last_glyphless_glyph_frame = NULL;
7998 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
7999 static int last_glyphless_glyph_merged_face_id = 0;
8000
8001 int
8002 merge_glyphless_glyph_face (struct it *it)
8003 {
8004 int face_id;
8005
8006 if (it->f == last_glyphless_glyph_frame
8007 && it->face_id == last_glyphless_glyph_face_id)
8008 face_id = last_glyphless_glyph_merged_face_id;
8009 else
8010 {
8011
8012 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8013 last_glyphless_glyph_frame = it->f;
8014 last_glyphless_glyph_face_id = it->face_id;
8015 last_glyphless_glyph_merged_face_id = face_id;
8016 }
8017 return face_id;
8018 }
8019
8020
8021
8022
8023 void
8024 forget_escape_and_glyphless_faces (void)
8025 {
8026 last_escape_glyph_frame = NULL;
8027 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8028 last_glyphless_glyph_frame = NULL;
8029 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8030 }
8031
8032
8033
8034
8035
8036 static bool
8037 get_next_display_element (struct it *it)
8038 {
8039
8040
8041
8042
8043 bool success_p;
8044
8045 get_next:
8046 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8047
8048 if (it->what == IT_CHARACTER)
8049 {
8050
8051
8052
8053
8054
8055 if (it->bidi_p && it->bidi_it.type == STRONG_R
8056 && !inhibit_bidi_mirroring)
8057 it->c = bidi_mirror_char (it->c);
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067 if (success_p && it->dpvec == NULL)
8068 {
8069 Lisp_Object dv;
8070 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8071 bool nonascii_space_p = false;
8072 bool nonascii_hyphen_p = false;
8073 int c = it->c;
8074
8075 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8076 {
8077 eassert (SINGLE_BYTE_CHAR_P (c));
8078 if (unibyte_display_via_language_environment)
8079 {
8080 c = DECODE_CHAR (unibyte, c);
8081 if (c < 0)
8082 c = BYTE8_TO_CHAR (it->c);
8083 }
8084 else
8085 c = BYTE8_TO_CHAR (it->c);
8086 }
8087
8088 if (it->dp
8089 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8090 VECTORP (dv)))
8091 {
8092 struct Lisp_Vector *v = XVECTOR (dv);
8093
8094
8095
8096
8097 if (v->header.size)
8098 {
8099 it->dpvec_char_len = it->len;
8100 it->dpvec = v->contents;
8101 it->dpend = v->contents + v->header.size;
8102 it->current.dpvec_index = 0;
8103 it->dpvec_face_id = -1;
8104 it->saved_face_id = it->face_id;
8105 it->method = GET_FROM_DISPLAY_VECTOR;
8106 it->ellipsis_p = false;
8107 }
8108 else
8109 {
8110 set_iterator_to_next (it, false);
8111 }
8112 goto get_next;
8113 }
8114
8115 if (! NILP (lookup_glyphless_char_display (c, it)))
8116 {
8117 if (it->what == IT_GLYPHLESS)
8118 goto done;
8119
8120 set_iterator_to_next (it, false);
8121 goto get_next;
8122 }
8123
8124
8125
8126 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8127 {
8128 if (blankp (c))
8129 nonascii_space_p = true;
8130 else if (c == SOFT_HYPHEN || c == HYPHEN
8131 || c == NON_BREAKING_HYPHEN)
8132 nonascii_hyphen_p = true;
8133 }
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146 if (((c < ' ' || c == 127)
8147 ? (it->area != TEXT_AREA
8148
8149 || (c != '\t'
8150 && it->glyph_row
8151 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8152 || (c != '\n' && c != '\t'))
8153 : (nonascii_space_p
8154 || nonascii_hyphen_p
8155 || CHAR_BYTE8_P (c)
8156 || ! CHAR_PRINTABLE_P (c))))
8157 {
8158
8159
8160
8161
8162
8163
8164 Lisp_Object gc;
8165 int ctl_len;
8166 int face_id;
8167 int lface_id = 0;
8168 int escape_glyph;
8169
8170
8171
8172 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8173 {
8174 int g;
8175
8176 g = '^';
8177
8178 if (it->dp
8179 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8180 {
8181 g = GLYPH_CODE_CHAR (gc);
8182 lface_id = GLYPH_CODE_FACE (gc);
8183 }
8184
8185 face_id = (lface_id
8186 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8187 : merge_escape_glyph_face (it));
8188
8189 XSETINT (it->ctl_chars[0], g);
8190 XSETINT (it->ctl_chars[1], c ^ 0100);
8191 ctl_len = 2;
8192 goto display_control;
8193 }
8194
8195
8196
8197
8198 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8199 {
8200
8201 face_id = merge_faces (it->w, Qnobreak_space, 0,
8202 it->face_id);
8203 XSETINT (it->ctl_chars[0],
8204 nobreak_char_ascii_display ? ' ' : it->c);
8205 ctl_len = 1;
8206 goto display_control;
8207 }
8208
8209
8210
8211
8212 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8213 {
8214
8215 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8216 it->face_id);
8217 XSETINT (it->ctl_chars[0],
8218 nobreak_char_ascii_display ? '-' : it->c);
8219 ctl_len = 1;
8220 goto display_control;
8221 }
8222
8223
8224
8225
8226 escape_glyph = '\\';
8227
8228 if (it->dp
8229 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8230 {
8231 escape_glyph = GLYPH_CODE_CHAR (gc);
8232 lface_id = GLYPH_CODE_FACE (gc);
8233 }
8234
8235 face_id = (lface_id
8236 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8237 : merge_escape_glyph_face (it));
8238
8239
8240
8241 if (nonascii_space_p || nonascii_hyphen_p)
8242 {
8243 XSETINT (it->ctl_chars[0], escape_glyph);
8244 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8245 ctl_len = 2;
8246 goto display_control;
8247 }
8248
8249 {
8250 char str[10];
8251 int len, i;
8252
8253 if (CHAR_BYTE8_P (c))
8254
8255 c = CHAR_TO_BYTE8 (c);
8256 const char *format_string = display_raw_bytes_as_hex
8257 ? "x%02x"
8258 : "%03o";
8259 len = sprintf (str, format_string, c + 0u);
8260
8261 XSETINT (it->ctl_chars[0], escape_glyph);
8262 for (i = 0; i < len; i++)
8263 XSETINT (it->ctl_chars[i + 1], str[i]);
8264 ctl_len = len + 1;
8265 }
8266
8267 display_control:
8268
8269 it->dpvec_char_len = it->len;
8270 it->dpvec = it->ctl_chars;
8271 it->dpend = it->dpvec + ctl_len;
8272 it->current.dpvec_index = 0;
8273 it->dpvec_face_id = face_id;
8274 it->saved_face_id = it->face_id;
8275 it->method = GET_FROM_DISPLAY_VECTOR;
8276 it->ellipsis_p = false;
8277 goto get_next;
8278 }
8279 it->char_to_display = c;
8280 }
8281 else if (success_p)
8282 {
8283 it->char_to_display = it->c;
8284 }
8285 }
8286
8287 #ifdef HAVE_WINDOW_SYSTEM
8288
8289
8290 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8291 && it->multibyte_p
8292 && success_p
8293 && FRAME_WINDOW_P (it->f))
8294 {
8295 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8296
8297 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8298 {
8299
8300 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8301
8302 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8303 }
8304 else
8305 {
8306 ptrdiff_t pos = (it->s ? -1
8307 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8308 : IT_CHARPOS (*it));
8309 int c;
8310
8311 if (it->what == IT_CHARACTER)
8312 c = it->char_to_display;
8313 else
8314 {
8315 struct composition *cmp = composition_table[it->cmp_it.id];
8316 int i;
8317
8318 c = ' ';
8319 for (i = 0; i < cmp->glyph_len; i++)
8320
8321
8322 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8323 break;
8324 }
8325 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8326 }
8327 }
8328 #endif
8329
8330 done:
8331
8332
8333 if (it->face_box_p
8334 && it->s == NULL)
8335 {
8336 if (it->method == GET_FROM_STRING && it->sp)
8337 {
8338 int face_id = underlying_face_id (it);
8339 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8340
8341 if (face)
8342 {
8343 if (face->box == FACE_NO_BOX)
8344 {
8345
8346
8347 int string_face_id = face_after_it_pos (it);
8348 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8349 it->end_of_box_run_p = true;
8350 }
8351
8352
8353
8354 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8355
8356
8357
8358 || (it->what == IT_COMPOSITION
8359 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8360 >= SCHARS (it->string))))
8361
8362
8363 && ((it->current.overlay_string_index >= 0
8364 && (it->current.overlay_string_index
8365 == it->n_overlay_strings - 1))
8366
8367 || it->from_disp_prop_p))
8368 {
8369 ptrdiff_t ignore;
8370 int next_face_id;
8371 bool text_from_string = false;
8372
8373
8374 struct text_pos pos = it->current.pos;
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386 if (it->from_disp_prop_p)
8387 {
8388 int stackp = it->sp - 1;
8389
8390
8391 while (stackp >= 0
8392 && STRINGP ((it->stack + stackp)->string))
8393 stackp--;
8394 if (stackp < 0)
8395 {
8396
8397
8398
8399
8400
8401
8402 text_from_string = true;
8403 pos = it->stack[it->sp - 1].position;
8404 }
8405 else
8406 pos = (it->stack + stackp)->position;
8407 }
8408 else
8409 INC_TEXT_POS (pos, it->multibyte_p);
8410
8411 if (text_from_string)
8412 {
8413 Lisp_Object base_string = it->stack[it->sp - 1].string;
8414
8415 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8416 it->end_of_box_run_p = true;
8417 else
8418 {
8419 next_face_id
8420 = face_at_string_position (it->w, base_string,
8421 CHARPOS (pos), 0,
8422 &ignore, face_id,
8423 false, 0);
8424 if (FACE_FROM_ID (it->f, next_face_id)->box
8425 == FACE_NO_BOX)
8426 it->end_of_box_run_p = true;
8427 }
8428 }
8429 else if (CHARPOS (pos) >= ZV)
8430 it->end_of_box_run_p = true;
8431 else
8432 {
8433 next_face_id =
8434 face_at_buffer_position (it->w, CHARPOS (pos),
8435 &ignore,
8436 CHARPOS (pos)
8437 + TEXT_PROP_DISTANCE_LIMIT,
8438 false, -1, 0);
8439 if (FACE_FROM_ID (it->f, next_face_id)->box
8440 == FACE_NO_BOX)
8441 it->end_of_box_run_p = true;
8442 }
8443 }
8444 }
8445 }
8446
8447
8448 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8449 {
8450 int face_id = face_after_it_pos (it);
8451 if (face_id != it->face_id
8452 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8453 it->end_of_box_run_p = true;
8454 }
8455 }
8456
8457
8458
8459
8460
8461 if (!success_p && it->sp > 0)
8462 {
8463 set_iterator_to_next (it, false);
8464 success_p = get_next_display_element (it);
8465 }
8466
8467
8468 return success_p;
8469 }
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487 void
8488 set_iterator_to_next (struct it *it, bool reseat_p)
8489 {
8490
8491 if (max_redisplay_ticks > 0)
8492 update_redisplay_ticks (1, it->w);
8493
8494 switch (it->method)
8495 {
8496 case GET_FROM_BUFFER:
8497
8498
8499
8500 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8501 reseat_at_next_visible_line_start (it, false);
8502 else if (it->cmp_it.id >= 0)
8503 {
8504
8505 if (! it->bidi_p)
8506 {
8507 IT_CHARPOS (*it) += it->cmp_it.nchars;
8508 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8509 }
8510 else
8511 {
8512 int i;
8513
8514
8515
8516
8517 for (i = 0; i < it->cmp_it.nchars; i++)
8518 bidi_move_to_visually_next (&it->bidi_it);
8519 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8520 IT_CHARPOS (*it) = it->bidi_it.charpos;
8521 }
8522
8523 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8524 && it->cmp_it.to < it->cmp_it.nglyphs)
8525 {
8526
8527
8528 it->cmp_it.from = it->cmp_it.to;
8529 }
8530 else if ((it->bidi_p && it->cmp_it.reversed_p)
8531 && it->cmp_it.from > 0)
8532 {
8533
8534
8535 it->cmp_it.to = it->cmp_it.from;
8536 }
8537 else
8538 {
8539
8540
8541 ptrdiff_t stop = it->end_charpos;
8542
8543 if (it->bidi_it.scan_dir < 0)
8544
8545
8546 stop = -1;
8547 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8548 IT_BYTEPOS (*it), stop, Qnil, true);
8549 }
8550 }
8551 else
8552 {
8553 eassert (it->len != 0);
8554
8555 if (!it->bidi_p)
8556 {
8557 IT_BYTEPOS (*it) += it->len;
8558 IT_CHARPOS (*it) += 1;
8559 }
8560 else
8561 {
8562 int prev_scan_dir = it->bidi_it.scan_dir;
8563
8564
8565 if (it->bidi_it.new_paragraph)
8566 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8567 false);
8568 bidi_move_to_visually_next (&it->bidi_it);
8569 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8570 IT_CHARPOS (*it) = it->bidi_it.charpos;
8571 if (prev_scan_dir != it->bidi_it.scan_dir)
8572 {
8573
8574
8575 ptrdiff_t stop = it->end_charpos;
8576 if (it->bidi_it.scan_dir < 0)
8577 stop = -1;
8578 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8579 IT_BYTEPOS (*it), stop, Qnil,
8580 true);
8581 }
8582 }
8583 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8584 }
8585 break;
8586
8587 case GET_FROM_C_STRING:
8588
8589 if (!it->bidi_p
8590
8591
8592
8593
8594 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8595 {
8596 IT_BYTEPOS (*it) += it->len;
8597 IT_CHARPOS (*it) += 1;
8598 }
8599 else
8600 {
8601 bidi_move_to_visually_next (&it->bidi_it);
8602 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8603 IT_CHARPOS (*it) = it->bidi_it.charpos;
8604 }
8605 break;
8606
8607 case GET_FROM_DISPLAY_VECTOR:
8608
8609
8610
8611
8612 ++it->current.dpvec_index;
8613
8614
8615
8616 it->face_id = it->saved_face_id;
8617
8618 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8619 {
8620 bool recheck_faces = it->ellipsis_p;
8621
8622 if (it->s)
8623 it->method = GET_FROM_C_STRING;
8624 else if (STRINGP (it->string))
8625 it->method = GET_FROM_STRING;
8626 else
8627 {
8628 it->method = GET_FROM_BUFFER;
8629 it->object = it->w->contents;
8630 }
8631
8632 it->dpvec = NULL;
8633 it->current.dpvec_index = -1;
8634
8635
8636 if (it->dpvec_char_len < 0)
8637 reseat_at_next_visible_line_start (it, true);
8638 else if (it->dpvec_char_len > 0)
8639 {
8640 it->len = it->dpvec_char_len;
8641 set_iterator_to_next (it, reseat_p);
8642 }
8643
8644
8645 if (recheck_faces)
8646 {
8647 if (it->method == GET_FROM_STRING)
8648 it->stop_charpos = IT_STRING_CHARPOS (*it);
8649 else
8650 it->stop_charpos = IT_CHARPOS (*it);
8651 }
8652 }
8653 break;
8654
8655 case GET_FROM_STRING:
8656
8657 eassert (it->s == NULL && STRINGP (it->string));
8658
8659
8660
8661
8662
8663 if (it->current.overlay_string_index >= 0)
8664 {
8665
8666
8667
8668 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8669 goto consider_string_end;
8670 }
8671 else
8672 {
8673
8674
8675 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8676 goto consider_string_end;
8677 }
8678 if (it->cmp_it.id >= 0)
8679 {
8680
8681
8682
8683 if (! it->bidi_p)
8684 {
8685 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8686 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8687 }
8688 else
8689 {
8690 int i;
8691
8692 for (i = 0; i < it->cmp_it.nchars; i++)
8693 bidi_move_to_visually_next (&it->bidi_it);
8694 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8695 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8696 }
8697
8698
8699
8700 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8701 && (it->cmp_it.to < it->cmp_it.nglyphs))
8702 {
8703
8704
8705 it->cmp_it.from = it->cmp_it.to;
8706 }
8707 else if ((it->bidi_p && it->cmp_it.reversed_p)
8708 && it->cmp_it.from > 0)
8709 {
8710
8711
8712 it->cmp_it.to = it->cmp_it.from;
8713 }
8714 else
8715 {
8716
8717
8718
8719
8720
8721
8722 ptrdiff_t stop = SCHARS (it->string);
8723
8724 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8725 stop = -1;
8726 else if (it->end_charpos < stop)
8727 {
8728
8729
8730
8731 stop = it->end_charpos;
8732 }
8733 composition_compute_stop_pos (&it->cmp_it,
8734 IT_STRING_CHARPOS (*it),
8735 IT_STRING_BYTEPOS (*it), stop,
8736 it->string, true);
8737 }
8738 }
8739 else
8740 {
8741 if (!it->bidi_p
8742
8743
8744
8745
8746
8747 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8748 {
8749 IT_STRING_BYTEPOS (*it) += it->len;
8750 IT_STRING_CHARPOS (*it) += 1;
8751 }
8752 else
8753 {
8754 int prev_scan_dir = it->bidi_it.scan_dir;
8755
8756 bidi_move_to_visually_next (&it->bidi_it);
8757 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8758 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8759
8760
8761 if (prev_scan_dir != it->bidi_it.scan_dir)
8762 {
8763 ptrdiff_t stop = SCHARS (it->string);
8764
8765 if (it->bidi_it.scan_dir < 0)
8766 stop = -1;
8767 else if (it->end_charpos < stop)
8768 stop = it->end_charpos;
8769
8770 composition_compute_stop_pos (&it->cmp_it,
8771 IT_STRING_CHARPOS (*it),
8772 IT_STRING_BYTEPOS (*it), stop,
8773 it->string, true);
8774 }
8775 }
8776 }
8777
8778 consider_string_end:
8779
8780 if (it->current.overlay_string_index >= 0)
8781 {
8782
8783
8784 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8785 {
8786 it->ellipsis_p = false;
8787 next_overlay_string (it);
8788 if (it->ellipsis_p)
8789 setup_for_ellipsis (it, 0);
8790 }
8791 }
8792 else
8793 {
8794
8795
8796
8797
8798 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8799 && it->sp > 0)
8800 {
8801 pop_it (it);
8802 if (it->method == GET_FROM_STRING)
8803 goto consider_string_end;
8804 }
8805 }
8806 break;
8807
8808 case GET_FROM_IMAGE:
8809 case GET_FROM_STRETCH:
8810 case GET_FROM_XWIDGET:
8811
8812
8813
8814
8815 eassert (it->sp > 0);
8816 pop_it (it);
8817 if (it->method == GET_FROM_STRING)
8818 goto consider_string_end;
8819 break;
8820
8821 default:
8822
8823 emacs_abort ();
8824 }
8825
8826 eassert (it->method != GET_FROM_STRING
8827 || (STRINGP (it->string)
8828 && IT_STRING_CHARPOS (*it) >= 0));
8829 }
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840 static bool
8841 next_element_from_display_vector (struct it *it)
8842 {
8843 Lisp_Object gc;
8844 int prev_face_id = it->face_id;
8845 int next_face_id;
8846
8847
8848 eassert (it->dpvec && it->current.dpvec_index >= 0);
8849
8850 it->face_id = it->saved_face_id;
8851
8852
8853
8854 if (it->dpend - it->dpvec > 0
8855 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8856 {
8857 struct face *this_face, *prev_face, *next_face;
8858
8859 it->c = GLYPH_CODE_CHAR (gc);
8860 it->len = CHAR_BYTES (it->c);
8861
8862
8863
8864
8865 if (it->dpvec_face_id >= 0)
8866 it->face_id = it->dpvec_face_id;
8867 else
8868 {
8869 int lface_id = GLYPH_CODE_FACE (gc);
8870 if (lface_id > 0)
8871 it->face_id = merge_faces (it->w, Qt, lface_id,
8872 it->saved_face_id);
8873 }
8874
8875
8876
8877
8878 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8879 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8880
8881
8882 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8883 && (!prev_face
8884 || prev_face->box == FACE_NO_BOX));
8885
8886
8887
8888
8889 next_face_id = it->saved_face_id;
8890 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8891 {
8892 if (it->dpvec_face_id >= 0)
8893 next_face_id = it->dpvec_face_id;
8894 else
8895 {
8896 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8897 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8898
8899 if (lface_id > 0)
8900 next_face_id = merge_faces (it->w, Qt, lface_id,
8901 it->saved_face_id);
8902 }
8903 }
8904 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8905 if (this_face && this_face->box != FACE_NO_BOX
8906 && (!next_face || next_face->box == FACE_NO_BOX))
8907 it->end_of_box_run_p = true;
8908 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8909 }
8910 else
8911
8912 it->c = ' ', it->len = 1;
8913
8914
8915
8916
8917 it->what = IT_CHARACTER;
8918 return true;
8919 }
8920
8921
8922
8923 static void
8924 get_visually_first_element (struct it *it)
8925 {
8926 bool string_p = STRINGP (it->string) || it->s;
8927 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8928 ptrdiff_t bob;
8929 ptrdiff_t obegv = BEGV;
8930
8931 SET_WITH_NARROWED_BEGV (it, bob,
8932 string_p ? 0 :
8933 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8934 it->medium_narrowing_begv);
8935
8936 if (STRINGP (it->string))
8937 {
8938 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8939 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8940 }
8941 else
8942 {
8943 it->bidi_it.charpos = IT_CHARPOS (*it);
8944 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8945 }
8946
8947 if (it->bidi_it.charpos == eob)
8948 {
8949
8950
8951
8952 it->bidi_it.first_elt = false;
8953 }
8954 else if (it->bidi_it.charpos == bob
8955 || (!string_p
8956 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8957 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8958 {
8959
8960
8961 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8962 bidi_move_to_visually_next (&it->bidi_it);
8963 }
8964 else
8965 {
8966 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
8967
8968
8969
8970
8971 if (string_p)
8972 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
8973 else
8974 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
8975 find_newline_no_quit (IT_CHARPOS (*it),
8976 IT_BYTEPOS (*it), -1,
8977 &it->bidi_it.bytepos),
8978 it->medium_narrowing_begv);
8979 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8980 do
8981 {
8982
8983
8984 bidi_move_to_visually_next (&it->bidi_it);
8985 }
8986 while (it->bidi_it.bytepos != orig_bytepos
8987 && it->bidi_it.charpos < eob);
8988 }
8989
8990
8991 if (STRINGP (it->string))
8992 {
8993 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8994 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8995 }
8996 else
8997 {
8998 IT_CHARPOS (*it) = it->bidi_it.charpos;
8999 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9000 }
9001
9002 if (STRINGP (it->string) || !it->s)
9003 {
9004 ptrdiff_t stop, charpos, bytepos;
9005
9006 if (STRINGP (it->string))
9007 {
9008 eassert (!it->s);
9009 stop = SCHARS (it->string);
9010 if (stop > it->end_charpos)
9011 stop = it->end_charpos;
9012 charpos = IT_STRING_CHARPOS (*it);
9013 bytepos = IT_STRING_BYTEPOS (*it);
9014 }
9015 else
9016 {
9017 stop = it->end_charpos;
9018 charpos = IT_CHARPOS (*it);
9019 bytepos = IT_BYTEPOS (*it);
9020 }
9021 if (it->bidi_it.scan_dir < 0)
9022 stop = -1;
9023 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9024 it->string, true);
9025 }
9026 }
9027
9028
9029
9030
9031
9032
9033 static bool
9034 next_element_from_string (struct it *it)
9035 {
9036 struct text_pos position;
9037
9038 eassert (STRINGP (it->string));
9039 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9040 eassert (IT_STRING_CHARPOS (*it) >= 0);
9041 position = it->current.string_pos;
9042
9043
9044
9045
9046
9047 if (it->bidi_p && it->bidi_it.first_elt)
9048 {
9049 get_visually_first_element (it);
9050 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9051 }
9052
9053
9054 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9055 {
9056 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9057 {
9058 if (!(!it->bidi_p
9059 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9060 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9061 {
9062
9063
9064
9065
9066
9067
9068 handle_stop_backwards (it, it->stop_charpos);
9069 return GET_NEXT_DISPLAY_ELEMENT (it);
9070 }
9071 else
9072 {
9073 if (it->bidi_p)
9074 {
9075
9076
9077 it->prev_stop = it->stop_charpos;
9078
9079
9080
9081 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9082 it->base_level_stop = it->stop_charpos;
9083 }
9084 handle_stop (it);
9085
9086
9087
9088 return GET_NEXT_DISPLAY_ELEMENT (it);
9089 }
9090 }
9091 else if (it->bidi_p
9092
9093
9094
9095 && IT_STRING_CHARPOS (*it) < it->prev_stop
9096
9097
9098
9099
9100 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9101 {
9102
9103
9104
9105
9106 if (it->base_level_stop <= 0
9107 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9108 it->base_level_stop = 0;
9109 handle_stop_backwards (it, it->base_level_stop);
9110 return GET_NEXT_DISPLAY_ELEMENT (it);
9111 }
9112 }
9113
9114 if (it->current.overlay_string_index >= 0)
9115 {
9116
9117
9118
9119 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9120 {
9121 it->what = IT_EOB;
9122 return false;
9123 }
9124 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9125 IT_STRING_BYTEPOS (*it),
9126 it->bidi_it.scan_dir < 0
9127 ? -1
9128 : SCHARS (it->string))
9129 && next_element_from_composition (it))
9130 {
9131 return true;
9132 }
9133 else if (STRING_MULTIBYTE (it->string))
9134 {
9135 const unsigned char *s = (SDATA (it->string)
9136 + IT_STRING_BYTEPOS (*it));
9137 it->c = check_char_and_length (s, &it->len);
9138 }
9139 else
9140 {
9141 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9142 it->len = 1;
9143 }
9144 }
9145 else
9146 {
9147
9148
9149
9150
9151 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9152 {
9153 it->what = IT_EOB;
9154 return false;
9155 }
9156 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9157 {
9158
9159 it->c = ' ', it->len = 1;
9160 CHARPOS (position) = BYTEPOS (position) = -1;
9161 }
9162 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9163 IT_STRING_BYTEPOS (*it),
9164 it->bidi_it.scan_dir < 0
9165 ? -1
9166 : it->string_nchars)
9167 && next_element_from_composition (it))
9168 {
9169 return true;
9170 }
9171 else if (STRING_MULTIBYTE (it->string))
9172 {
9173 const unsigned char *s = (SDATA (it->string)
9174 + IT_STRING_BYTEPOS (*it));
9175 it->c = check_char_and_length (s, &it->len);
9176 }
9177 else
9178 {
9179 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9180 it->len = 1;
9181 }
9182 }
9183
9184
9185 it->what = IT_CHARACTER;
9186 it->object = it->string;
9187 it->position = position;
9188 return true;
9189 }
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199 static bool
9200 next_element_from_c_string (struct it *it)
9201 {
9202 bool success_p = true;
9203
9204 eassert (it->s);
9205 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9206 it->what = IT_CHARACTER;
9207 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9208 it->object = make_fixnum (0);
9209
9210
9211
9212
9213
9214 if (it->bidi_p && it->bidi_it.first_elt)
9215 get_visually_first_element (it);
9216
9217
9218
9219
9220 if (IT_CHARPOS (*it) >= it->end_charpos)
9221 {
9222
9223 it->what = IT_EOB;
9224 success_p = false;
9225 }
9226 else if (IT_CHARPOS (*it) >= it->string_nchars)
9227 {
9228
9229 it->c = ' ', it->len = 1;
9230 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9231 }
9232 else if (it->multibyte_p)
9233 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9234 else
9235 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9236
9237 return success_p;
9238 }
9239
9240
9241
9242
9243
9244
9245
9246 static bool
9247 next_element_from_ellipsis (struct it *it)
9248 {
9249 if (it->selective_display_ellipsis_p)
9250 setup_for_ellipsis (it, it->len);
9251 else
9252 {
9253
9254
9255
9256
9257 it->saved_face_id = it->face_id;
9258 it->method = GET_FROM_BUFFER;
9259 it->object = it->w->contents;
9260 reseat_at_next_visible_line_start (it, true);
9261 it->face_before_selective_p = true;
9262 }
9263
9264 return GET_NEXT_DISPLAY_ELEMENT (it);
9265 }
9266
9267
9268
9269
9270
9271
9272
9273 static bool
9274 next_element_from_image (struct it *it)
9275 {
9276 it->what = IT_IMAGE;
9277 return true;
9278 }
9279
9280 static bool
9281 next_element_from_xwidget (struct it *it)
9282 {
9283 it->what = IT_XWIDGET;
9284 return true;
9285 }
9286
9287
9288
9289
9290
9291
9292 static bool
9293 next_element_from_stretch (struct it *it)
9294 {
9295 it->what = IT_STRETCH;
9296 return true;
9297 }
9298
9299
9300
9301
9302
9303
9304 static void
9305 compute_stop_pos_backwards (struct it *it)
9306 {
9307 const int SCAN_BACK_LIMIT = 1000;
9308 struct text_pos pos;
9309 struct display_pos save_current = it->current;
9310 struct text_pos save_position = it->position;
9311 ptrdiff_t charpos = IT_CHARPOS (*it);
9312 ptrdiff_t where_we_are = charpos;
9313 ptrdiff_t save_stop_pos = it->stop_charpos;
9314 ptrdiff_t save_end_pos = it->end_charpos;
9315
9316 eassert (NILP (it->string) && !it->s);
9317 eassert (it->bidi_p);
9318 it->bidi_p = false;
9319 do
9320 {
9321 it->end_charpos = min (charpos + 1, ZV);
9322 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9323 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9324 reseat_1 (it, pos, false);
9325 compute_stop_pos (it);
9326
9327 if (it->stop_charpos <= charpos)
9328 emacs_abort ();
9329 }
9330 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9331
9332 if (it->stop_charpos <= where_we_are)
9333 it->prev_stop = it->stop_charpos;
9334 else
9335 it->prev_stop = BEGV;
9336 it->bidi_p = true;
9337 it->current = save_current;
9338 it->position = save_position;
9339 it->stop_charpos = save_stop_pos;
9340 it->end_charpos = save_end_pos;
9341 }
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351 static void
9352 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9353 {
9354 bool bufp = !STRINGP (it->string);
9355 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9356 struct display_pos save_current = it->current;
9357 struct text_pos save_position = it->position;
9358 struct composition_it save_cmp_it = it->cmp_it;
9359 struct text_pos pos1;
9360 ptrdiff_t next_stop;
9361
9362
9363 eassert (it->bidi_p);
9364 it->bidi_p = false;
9365 do
9366 {
9367 it->prev_stop = charpos;
9368 if (bufp)
9369 {
9370 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9371 reseat_1 (it, pos1, false);
9372 }
9373 else
9374 it->current.string_pos = string_pos (charpos, it->string);
9375 compute_stop_pos (it);
9376
9377 if (it->stop_charpos <= it->prev_stop)
9378 emacs_abort ();
9379 charpos = it->stop_charpos;
9380 }
9381 while (charpos <= where_we_are);
9382
9383 it->bidi_p = true;
9384 it->current = save_current;
9385 it->position = save_position;
9386 it->cmp_it = save_cmp_it;
9387 next_stop = it->stop_charpos;
9388 it->stop_charpos = it->prev_stop;
9389 handle_stop (it);
9390 it->stop_charpos = next_stop;
9391 }
9392
9393
9394
9395
9396
9397
9398 static bool
9399 next_element_from_buffer (struct it *it)
9400 {
9401 bool success_p = true;
9402
9403 eassert (IT_CHARPOS (*it) >= BEGV);
9404 eassert (NILP (it->string) && !it->s);
9405 eassert (!it->bidi_p
9406 || (NILP (it->bidi_it.string.lstring)
9407 && it->bidi_it.string.s == NULL));
9408
9409
9410
9411
9412
9413 if (it->bidi_p && it->bidi_it.first_elt)
9414 {
9415 get_visually_first_element (it);
9416 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9417 }
9418
9419 if (IT_CHARPOS (*it) >= it->stop_charpos)
9420 {
9421 if (IT_CHARPOS (*it) >= it->end_charpos)
9422 {
9423 bool overlay_strings_follow_p;
9424
9425
9426
9427 if (it->overlay_strings_at_end_processed_p)
9428 overlay_strings_follow_p = false;
9429 else
9430 {
9431 it->overlay_strings_at_end_processed_p = true;
9432 overlay_strings_follow_p = get_overlay_strings (it, 0);
9433 }
9434
9435 if (overlay_strings_follow_p)
9436 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9437 else
9438 {
9439 it->what = IT_EOB;
9440 it->position = it->current.pos;
9441 success_p = false;
9442 }
9443 }
9444 else if (!(!it->bidi_p
9445 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9446 || IT_CHARPOS (*it) == it->stop_charpos))
9447 {
9448
9449
9450
9451
9452
9453
9454 handle_stop_backwards (it, it->stop_charpos);
9455 it->ignore_overlay_strings_at_pos_p = false;
9456 return GET_NEXT_DISPLAY_ELEMENT (it);
9457 }
9458 else
9459 {
9460 if (it->bidi_p)
9461 {
9462
9463
9464 it->prev_stop = it->stop_charpos;
9465
9466
9467
9468 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9469 it->base_level_stop = it->stop_charpos;
9470 }
9471 handle_stop (it);
9472 it->ignore_overlay_strings_at_pos_p = false;
9473 return GET_NEXT_DISPLAY_ELEMENT (it);
9474 }
9475 }
9476 else if (it->bidi_p
9477
9478
9479
9480 && IT_CHARPOS (*it) < it->prev_stop
9481
9482
9483
9484
9485 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9486 {
9487 if (it->base_level_stop <= 0
9488 || IT_CHARPOS (*it) < it->base_level_stop)
9489 {
9490
9491
9492
9493
9494 it->base_level_stop = BEGV;
9495 compute_stop_pos_backwards (it);
9496 handle_stop_backwards (it, it->prev_stop);
9497 }
9498 else
9499 handle_stop_backwards (it, it->base_level_stop);
9500 it->ignore_overlay_strings_at_pos_p = false;
9501 return GET_NEXT_DISPLAY_ELEMENT (it);
9502 }
9503 else
9504 {
9505
9506
9507 unsigned char *p;
9508 ptrdiff_t stop;
9509
9510
9511
9512 it->ignore_overlay_strings_at_pos_p = false;
9513
9514 if (composition_break_at_point
9515 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9516 && !NILP (Vauto_composition_mode))
9517 {
9518
9519 if (it->bidi_it.scan_dir < 0)
9520 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9521 else
9522 stop = (IT_CHARPOS (*it) < PT
9523 && PT < it->end_charpos) ? PT : it->end_charpos;
9524 }
9525 else
9526 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9527 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9528 stop)
9529 && next_element_from_composition (it))
9530 {
9531 return true;
9532 }
9533
9534
9535 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9536 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9537 it->c = string_char_and_length (p, &it->len);
9538 else
9539 it->c = *p, it->len = 1;
9540
9541
9542 it->what = IT_CHARACTER;
9543 it->object = it->w->contents;
9544 it->position = it->current.pos;
9545
9546
9547
9548 if (it->selective)
9549 {
9550 if (it->c == '\n')
9551 {
9552
9553
9554 if (it->selective > 0
9555 && IT_CHARPOS (*it) + 1 < ZV
9556 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9557 IT_BYTEPOS (*it) + 1,
9558 it->selective))
9559 {
9560 success_p = next_element_from_ellipsis (it);
9561 it->dpvec_char_len = -1;
9562 }
9563 }
9564 else if (it->c == '\r' && it->selective == -1)
9565 {
9566
9567
9568
9569 success_p = next_element_from_ellipsis (it);
9570 it->dpvec_char_len = -1;
9571 }
9572 }
9573 }
9574
9575
9576 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9577 return success_p;
9578 }
9579
9580
9581
9582
9583
9584
9585
9586 static bool
9587 next_element_from_composition (struct it *it)
9588 {
9589 it->what = IT_COMPOSITION;
9590 it->len = it->cmp_it.nbytes;
9591 if (STRINGP (it->string))
9592 {
9593 if (it->c < 0)
9594 {
9595 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9596 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9597 return false;
9598 }
9599 it->position = it->current.string_pos;
9600 it->object = it->string;
9601 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9602 IT_STRING_BYTEPOS (*it), it->string);
9603 }
9604 else
9605 {
9606 if (it->c < 0)
9607 {
9608 IT_CHARPOS (*it) += it->cmp_it.nchars;
9609 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9610 if (it->bidi_p)
9611 {
9612 if (it->bidi_it.new_paragraph)
9613 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9614 false);
9615
9616
9617 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9618 bidi_move_to_visually_next (&it->bidi_it);
9619 }
9620 return false;
9621 }
9622 it->position = it->current.pos;
9623 it->object = it->w->contents;
9624 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9625 IT_BYTEPOS (*it), Qnil);
9626 }
9627 return true;
9628 }
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9640 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676 static enum move_it_result
9677 move_it_in_display_line_to (struct it *it,
9678 ptrdiff_t to_charpos, int to_x,
9679 enum move_operation_enum op)
9680 {
9681 enum move_it_result result = MOVE_UNDEFINED;
9682 struct glyph_row *saved_glyph_row;
9683 struct it wrap_it, atpos_it, atx_it, ppos_it;
9684 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9685 void *ppos_data = NULL;
9686 bool may_wrap = false;
9687 enum it_method prev_method = it->method;
9688 ptrdiff_t closest_pos UNINIT;
9689 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9690 bool saw_smaller_pos = prev_pos < to_charpos;
9691 bool line_number_pending = false;
9692
9693
9694 saved_glyph_row = it->glyph_row;
9695 it->glyph_row = NULL;
9696
9697
9698
9699
9700
9701
9702 wrap_it.sp = -1;
9703 atpos_it.sp = -1;
9704 atx_it.sp = -1;
9705
9706
9707
9708
9709
9710
9711
9712
9713 if (it->bidi_p)
9714 {
9715 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9716 {
9717 SAVE_IT (ppos_it, *it, ppos_data);
9718 closest_pos = IT_CHARPOS (*it);
9719 }
9720 else
9721 closest_pos = ZV;
9722 }
9723
9724 #define BUFFER_POS_REACHED_P() \
9725 ((op & MOVE_TO_POS) != 0 \
9726 && BUFFERP (it->object) \
9727 && (IT_CHARPOS (*it) == to_charpos \
9728 || ((!it->bidi_p \
9729 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9730 && IT_CHARPOS (*it) > to_charpos) \
9731 || (it->what == IT_COMPOSITION \
9732 && ((IT_CHARPOS (*it) > to_charpos \
9733 && to_charpos >= it->cmp_it.charpos) \
9734 || (IT_CHARPOS (*it) < to_charpos \
9735 && to_charpos <= it->cmp_it.charpos)))) \
9736 && (it->method == GET_FROM_BUFFER \
9737 || (it->method == GET_FROM_DISPLAY_VECTOR \
9738 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9739
9740 if (it->hpos == 0)
9741 {
9742
9743
9744
9745
9746 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9747 && should_produce_line_number (it))
9748 {
9749 if (it->current_x == it->first_visible_x)
9750 maybe_produce_line_number (it);
9751 else
9752 line_number_pending = true;
9753 }
9754
9755 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9756 handle_line_prefix (it);
9757 }
9758
9759 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9760 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9761
9762 while (true)
9763 {
9764 int x, i, ascent = 0, descent = 0;
9765
9766
9767 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9768 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9769 (IT)->max_descent = descent)
9770
9771
9772
9773 if ((op & MOVE_TO_POS) != 0
9774 && BUFFERP (it->object)
9775 && it->method == GET_FROM_BUFFER
9776 && (((!it->bidi_p
9777
9778
9779
9780
9781 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9782 && IT_CHARPOS (*it) > to_charpos)
9783 || (it->bidi_p
9784 && (prev_method == GET_FROM_IMAGE
9785 || prev_method == GET_FROM_STRETCH
9786 || prev_method == GET_FROM_STRING)
9787
9788 && ((prev_pos < to_charpos
9789 && IT_CHARPOS (*it) >= to_charpos)
9790
9791 || (prev_pos > to_charpos
9792 && IT_CHARPOS (*it) <= to_charpos)))))
9793 {
9794 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9795 {
9796 result = MOVE_POS_MATCH_OR_ZV;
9797 break;
9798 }
9799 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9800
9801
9802
9803 SAVE_IT (atpos_it, *it, atpos_data);
9804 }
9805
9806
9807
9808
9809
9810 if (!get_next_display_element (it))
9811 {
9812 result = MOVE_POS_MATCH_OR_ZV;
9813 break;
9814 }
9815
9816 if (it->line_wrap == TRUNCATE)
9817 {
9818
9819
9820
9821
9822
9823
9824 if (BUFFER_POS_REACHED_P ()
9825 && (it->pixel_width > 0
9826 || IT_CHARPOS (*it) > to_charpos
9827 || it->area != TEXT_AREA))
9828 {
9829 result = MOVE_POS_MATCH_OR_ZV;
9830 break;
9831 }
9832 }
9833 else
9834 {
9835 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9836 {
9837 bool next_may_wrap = may_wrap;
9838
9839 if (char_can_wrap_after (it))
9840 next_may_wrap = true;
9841 else
9842 next_may_wrap = false;
9843
9844 if (may_wrap && char_can_wrap_before (it))
9845 {
9846
9847
9848
9849
9850
9851 if (atpos_it.sp >= 0)
9852 {
9853 RESTORE_IT (it, &atpos_it, atpos_data);
9854 result = MOVE_POS_MATCH_OR_ZV;
9855 goto done;
9856 }
9857 if (atx_it.sp >= 0)
9858 {
9859 RESTORE_IT (it, &atx_it, atx_data);
9860 result = MOVE_X_REACHED;
9861 goto done;
9862 }
9863
9864 SAVE_IT (wrap_it, *it, wrap_data);
9865 }
9866
9867 may_wrap = next_may_wrap;
9868 }
9869 }
9870
9871
9872
9873 ascent = it->max_ascent;
9874 descent = it->max_descent;
9875
9876
9877
9878
9879
9880 x = it->current_x;
9881
9882 PRODUCE_GLYPHS (it);
9883
9884 if (it->area != TEXT_AREA)
9885 {
9886 prev_method = it->method;
9887 if (it->method == GET_FROM_BUFFER)
9888 prev_pos = IT_CHARPOS (*it);
9889 set_iterator_to_next (it, true);
9890 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9891 SET_TEXT_POS (this_line_min_pos,
9892 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9893 if (it->bidi_p
9894 && (op & MOVE_TO_POS)
9895 && IT_CHARPOS (*it) > to_charpos
9896 && IT_CHARPOS (*it) < closest_pos)
9897 closest_pos = IT_CHARPOS (*it);
9898 continue;
9899 }
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919 if (it->nglyphs)
9920 {
9921
9922
9923 int single_glyph_width = it->pixel_width / it->nglyphs;
9924 int new_x;
9925 int x_before_this_char = x;
9926 int hpos_before_this_char = it->hpos;
9927
9928 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9929 {
9930 new_x = x + single_glyph_width;
9931
9932
9933 if ((op & MOVE_TO_X) && new_x > to_x)
9934 {
9935 if (BUFFER_POS_REACHED_P ())
9936 {
9937 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9938 goto buffer_pos_reached;
9939 if (atpos_it.sp < 0)
9940 {
9941 SAVE_IT (atpos_it, *it, atpos_data);
9942 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9943 }
9944 }
9945 else
9946 {
9947 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9948 {
9949 it->current_x = x;
9950 result = MOVE_X_REACHED;
9951 break;
9952 }
9953 if (atx_it.sp < 0)
9954 {
9955 SAVE_IT (atx_it, *it, atx_data);
9956 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9957 }
9958 }
9959 }
9960
9961 if (
9962 it->line_wrap != TRUNCATE
9963 && (
9964 new_x > it->last_visible_x
9965
9966
9967 || (new_x == it->last_visible_x
9968 && FRAME_WINDOW_P (it->f)
9969 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
9970 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
9971 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
9972 {
9973 bool moved_forward = false;
9974
9975 if (
9976
9977 it->hpos == 0
9978 || (new_x == it->last_visible_x
9979 && FRAME_WINDOW_P (it->f)))
9980 {
9981 ++it->hpos;
9982 it->current_x = new_x;
9983
9984
9985
9986 if (i == it->nglyphs - 1)
9987 {
9988
9989
9990
9991 if (BUFFER_POS_REACHED_P ())
9992 {
9993 bool can_wrap = true;
9994
9995
9996
9997
9998
9999 if (it->line_wrap == WORD_WRAP
10000 && wrap_it.sp >= 0
10001 && may_wrap
10002 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10003 {
10004 struct it tem_it;
10005 void *tem_data = NULL;
10006
10007 SAVE_IT (tem_it, *it, tem_data);
10008 set_iterator_to_next (it, true);
10009 if (get_next_display_element (it)
10010 && !char_can_wrap_before (it))
10011 can_wrap = false;
10012 RESTORE_IT (it, &tem_it, tem_data);
10013 }
10014 if (it->line_wrap != WORD_WRAP
10015 || wrap_it.sp < 0
10016
10017
10018
10019
10020
10021
10022
10023 || (may_wrap && can_wrap
10024 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10025 {
10026 it->hpos = hpos_before_this_char;
10027 it->current_x = x_before_this_char;
10028 result = MOVE_POS_MATCH_OR_ZV;
10029 break;
10030 }
10031 if (it->line_wrap == WORD_WRAP
10032 && atpos_it.sp < 0)
10033 {
10034 SAVE_IT (atpos_it, *it, atpos_data);
10035 atpos_it.current_x = x_before_this_char;
10036 atpos_it.hpos = hpos_before_this_char;
10037 }
10038 }
10039
10040 prev_method = it->method;
10041 if (it->method == GET_FROM_BUFFER)
10042 prev_pos = IT_CHARPOS (*it);
10043 set_iterator_to_next (it, true);
10044 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10045 SET_TEXT_POS (this_line_min_pos,
10046 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10047
10048
10049
10050
10051
10052
10053
10054 if (!FRAME_WINDOW_P (it->f)
10055 || ((it->bidi_p
10056 && it->bidi_it.paragraph_dir == R2L)
10057 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10058 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10059 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10060 {
10061 if (!get_next_display_element (it))
10062 {
10063 result = MOVE_POS_MATCH_OR_ZV;
10064 break;
10065 }
10066 moved_forward = true;
10067 if (BUFFER_POS_REACHED_P ())
10068 {
10069 if (ITERATOR_AT_END_OF_LINE_P (it))
10070 result = MOVE_POS_MATCH_OR_ZV;
10071 else
10072 result = MOVE_LINE_CONTINUED;
10073 break;
10074 }
10075 if (ITERATOR_AT_END_OF_LINE_P (it)
10076 && (it->line_wrap != WORD_WRAP
10077 || wrap_it.sp < 0
10078 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10079 {
10080 result = MOVE_NEWLINE_OR_CR;
10081 break;
10082 }
10083 }
10084 }
10085 }
10086 else
10087 IT_RESET_X_ASCENT_DESCENT (it);
10088
10089
10090
10091
10092
10093
10094 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10095
10096
10097
10098
10099
10100 && (!moved_forward || char_can_wrap_before (it)))
10101 {
10102
10103
10104 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10105 && atx_it.sp >= 0)
10106 {
10107 RESTORE_IT (it, &atx_it, atx_data);
10108 atpos_it.sp = -1;
10109 atx_it.sp = -1;
10110 result = MOVE_X_REACHED;
10111 break;
10112 }
10113 }
10114 else if (wrap_it.sp >= 0)
10115 {
10116 RESTORE_IT (it, &wrap_it, wrap_data);
10117 atpos_it.sp = -1;
10118 atx_it.sp = -1;
10119 }
10120
10121 move_trace ("move_it_in: continued at %td\n",
10122 IT_CHARPOS (*it));
10123 result = MOVE_LINE_CONTINUED;
10124 break;
10125 }
10126
10127 if (BUFFER_POS_REACHED_P ())
10128 {
10129 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10130 goto buffer_pos_reached;
10131 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10132 {
10133 SAVE_IT (atpos_it, *it, atpos_data);
10134 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10135 }
10136 }
10137
10138 if (new_x > it->first_visible_x)
10139 {
10140
10141
10142 if (line_number_pending)
10143 {
10144 line_number_pending = false;
10145 it->current_x = it->first_visible_x;
10146 maybe_produce_line_number (it);
10147 it->current_x += new_x - it->first_visible_x;
10148 }
10149
10150
10151 ++it->hpos;
10152 }
10153 }
10154
10155 if (result != MOVE_UNDEFINED)
10156 break;
10157 }
10158 else if (BUFFER_POS_REACHED_P ())
10159 {
10160 buffer_pos_reached:
10161 IT_RESET_X_ASCENT_DESCENT (it);
10162 result = MOVE_POS_MATCH_OR_ZV;
10163 break;
10164 }
10165 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10166 {
10167
10168
10169
10170
10171 eassert (it->nglyphs == 0);
10172 result = MOVE_X_REACHED;
10173 break;
10174 }
10175
10176
10177 if (ITERATOR_AT_END_OF_LINE_P (it))
10178 {
10179
10180
10181
10182
10183 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10184 {
10185 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10186 {
10187 if (closest_pos < ZV)
10188 {
10189 RESTORE_IT (it, &ppos_it, ppos_data);
10190
10191
10192 if (closest_pos != to_charpos)
10193 move_it_in_display_line_to (it, closest_pos, -1,
10194 MOVE_TO_POS);
10195 result = MOVE_POS_MATCH_OR_ZV;
10196 }
10197 else
10198 goto buffer_pos_reached;
10199 }
10200 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10201 && IT_CHARPOS (*it) > to_charpos)
10202 goto buffer_pos_reached;
10203 else
10204 result = MOVE_NEWLINE_OR_CR;
10205 }
10206 else
10207 result = MOVE_NEWLINE_OR_CR;
10208
10209
10210
10211
10212 if (it->line_wrap == TRUNCATE
10213 && it->current_x <= it->first_visible_x
10214 && result == MOVE_NEWLINE_OR_CR
10215 && it->char_to_display == '\n')
10216 {
10217 it->max_ascent = it->ascent;
10218 it->max_descent = it->descent;
10219 }
10220
10221
10222
10223 if (result == MOVE_NEWLINE_OR_CR)
10224 it->constrain_row_ascent_descent_p = false;
10225 break;
10226 }
10227
10228 prev_method = it->method;
10229 if (it->method == GET_FROM_BUFFER)
10230 prev_pos = IT_CHARPOS (*it);
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240 bool overwide_wrap_prefix =
10241 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10242 && it->sp > 0 && it->method == GET_FROM_STRETCH
10243 && it->current_x >= it->last_visible_x
10244 && it->continuation_lines_width > 0
10245 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10246
10247
10248 if (!overwide_wrap_prefix)
10249 set_iterator_to_next (it, true);
10250 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10251 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10252 if (IT_CHARPOS (*it) < to_charpos)
10253 saw_smaller_pos = true;
10254 if (it->bidi_p
10255 && (op & MOVE_TO_POS)
10256 && IT_CHARPOS (*it) >= to_charpos
10257 && IT_CHARPOS (*it) < closest_pos)
10258 closest_pos = IT_CHARPOS (*it);
10259
10260
10261
10262 if (it->line_wrap == TRUNCATE
10263 && it->current_x >= it->last_visible_x)
10264 {
10265 if (!FRAME_WINDOW_P (it->f)
10266 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10267 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10268 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10269 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10270 {
10271 bool at_eob_p = false;
10272
10273 if ((at_eob_p = !get_next_display_element (it))
10274 || BUFFER_POS_REACHED_P ()
10275
10276
10277
10278
10279 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10280 && !saw_smaller_pos
10281 && IT_CHARPOS (*it) > to_charpos))
10282 {
10283 if (it->bidi_p
10284 && !BUFFER_POS_REACHED_P ()
10285 && !at_eob_p && closest_pos < ZV)
10286 {
10287 RESTORE_IT (it, &ppos_it, ppos_data);
10288 if (closest_pos != to_charpos)
10289 move_it_in_display_line_to (it, closest_pos, -1,
10290 MOVE_TO_POS);
10291 }
10292 result = MOVE_POS_MATCH_OR_ZV;
10293 break;
10294 }
10295 if (ITERATOR_AT_END_OF_LINE_P (it))
10296 {
10297 result = MOVE_NEWLINE_OR_CR;
10298 break;
10299 }
10300 }
10301 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10302 && !saw_smaller_pos
10303 && IT_CHARPOS (*it) > to_charpos)
10304 {
10305 if (closest_pos < ZV)
10306 {
10307 RESTORE_IT (it, &ppos_it, ppos_data);
10308 if (closest_pos != to_charpos)
10309 move_it_in_display_line_to (it, closest_pos, -1,
10310 MOVE_TO_POS);
10311 }
10312 result = MOVE_POS_MATCH_OR_ZV;
10313 break;
10314 }
10315 result = MOVE_LINE_TRUNCATED;
10316 break;
10317 }
10318 #undef IT_RESET_X_ASCENT_DESCENT
10319 }
10320
10321 #undef BUFFER_POS_REACHED_P
10322
10323
10324
10325
10326
10327
10328 if (result == MOVE_LINE_CONTINUED
10329 && it->line_wrap == WORD_WRAP
10330 && wrap_it.sp >= 0
10331 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10332 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10333 RESTORE_IT (it, &wrap_it, wrap_data);
10334 else if (atpos_it.sp >= 0)
10335 RESTORE_IT (it, &atpos_it, atpos_data);
10336 else if (atx_it.sp >= 0)
10337 RESTORE_IT (it, &atx_it, atx_data);
10338
10339 done:
10340
10341 if (atpos_data)
10342 bidi_unshelve_cache (atpos_data, true);
10343 if (atx_data)
10344 bidi_unshelve_cache (atx_data, true);
10345 if (wrap_data)
10346 bidi_unshelve_cache (wrap_data, true);
10347 if (ppos_data)
10348 bidi_unshelve_cache (ppos_data, true);
10349
10350
10351
10352 it->glyph_row = saved_glyph_row;
10353 return result;
10354 }
10355
10356
10357 void
10358 move_it_in_display_line (struct it *it,
10359 ptrdiff_t to_charpos, int to_x,
10360 enum move_operation_enum op)
10361 {
10362 if (it->line_wrap == WORD_WRAP
10363 && (op & MOVE_TO_X))
10364 {
10365 struct it save_it;
10366 void *save_data = NULL;
10367 int skip;
10368
10369 SAVE_IT (save_it, *it, save_data);
10370 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10371
10372
10373
10374
10375 if (skip == MOVE_LINE_CONTINUED)
10376 {
10377 int prev_x = max (it->current_x - 1, 0);
10378 RESTORE_IT (it, &save_it, save_data);
10379 move_it_in_display_line_to
10380 (it, -1, prev_x, MOVE_TO_X);
10381 }
10382 else
10383 bidi_unshelve_cache (save_data, true);
10384 }
10385 else
10386 move_it_in_display_line_to (it, to_charpos, to_x, op);
10387 }
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404 int
10405 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10406 {
10407 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10408 int line_height, line_start_x = 0, reached = 0;
10409 int max_current_x = 0;
10410 void *backup_data = NULL;
10411 ptrdiff_t orig_charpos = -1;
10412 enum it_method orig_method = NUM_IT_METHODS;
10413
10414 for (;;)
10415 {
10416 orig_charpos = IT_CHARPOS (*it);
10417 orig_method = it->method;
10418 if (op & MOVE_TO_VPOS)
10419 {
10420
10421
10422 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10423 {
10424 if (it->vpos == to_vpos)
10425 {
10426 reached = 1;
10427 break;
10428 }
10429 else
10430 skip = move_it_in_display_line_to (it, -1, -1, 0);
10431 }
10432 else
10433 {
10434
10435
10436 if (it->vpos == to_vpos)
10437 {
10438 reached = 2;
10439 break;
10440 }
10441
10442 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10443
10444 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10445 {
10446 reached = 3;
10447 break;
10448 }
10449 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10450 {
10451
10452 skip = move_it_in_display_line_to (it, to_charpos,
10453 -1, MOVE_TO_POS);
10454 if (skip == MOVE_POS_MATCH_OR_ZV)
10455 {
10456 reached = 4;
10457 break;
10458 }
10459 }
10460 }
10461 }
10462 else if (op & MOVE_TO_Y)
10463 {
10464 struct it it_backup;
10465
10466 if (it->line_wrap == WORD_WRAP)
10467 SAVE_IT (it_backup, *it, backup_data);
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481 skip = move_it_in_display_line_to
10482 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10483 (MOVE_TO_X | (op & MOVE_TO_POS)));
10484
10485
10486 if (skip == MOVE_POS_MATCH_OR_ZV)
10487 reached = 5;
10488 else if (skip == MOVE_X_REACHED)
10489 {
10490
10491
10492
10493
10494 line_height = it->max_ascent + it->max_descent;
10495 if (to_y >= it->current_y
10496 && to_y < it->current_y + line_height)
10497 {
10498 reached = 6;
10499 break;
10500 }
10501 SAVE_IT (it_backup, *it, backup_data);
10502 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10503 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10504 op & MOVE_TO_POS);
10505 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10506 line_height = it->max_ascent + it->max_descent;
10507 move_trace ("move_it: line_height = %d\n", line_height);
10508
10509 if (to_y >= it->current_y
10510 && to_y < it->current_y + line_height)
10511 {
10512
10513
10514
10515
10516
10517
10518
10519
10520 int max_ascent = it->max_ascent;
10521 int max_descent = it->max_descent;
10522
10523 RESTORE_IT (it, &it_backup, backup_data);
10524 it->max_ascent = max_ascent;
10525 it->max_descent = max_descent;
10526 reached = 6;
10527 }
10528 else
10529 {
10530 skip = skip2;
10531 if (skip == MOVE_POS_MATCH_OR_ZV)
10532 {
10533 reached = 7;
10534
10535
10536
10537
10538
10539
10540
10541 if (to_charpos > 0
10542 && IT_CHARPOS (*it) != to_charpos
10543 && ((IT_CHARPOS (it_backup) > to_charpos)
10544 == (IT_CHARPOS (*it) > to_charpos)))
10545 {
10546 int max_ascent = it->max_ascent;
10547 int max_descent = it->max_descent;
10548
10549 RESTORE_IT (it, &it_backup, backup_data);
10550 it->max_ascent = max_ascent;
10551 it->max_descent = max_descent;
10552 }
10553 }
10554 }
10555 }
10556 else
10557 {
10558
10559 line_height = it->max_ascent + it->max_descent;
10560 move_trace ("move_it: line_height = %d\n", line_height);
10561
10562 if (to_y >= it->current_y
10563 && to_y < it->current_y + line_height)
10564 {
10565 if (to_y > it->current_y)
10566 max_current_x = max (it->current_x, max_current_x);
10567
10568
10569
10570
10571
10572 if (skip == MOVE_LINE_CONTINUED
10573 && it->line_wrap == WORD_WRAP)
10574 {
10575 int prev_x = max (it->current_x - 1, 0);
10576 RESTORE_IT (it, &it_backup, backup_data);
10577 skip = move_it_in_display_line_to
10578 (it, -1, prev_x, MOVE_TO_X);
10579 }
10580
10581 reached = 6;
10582 }
10583 }
10584
10585 if (reached)
10586 {
10587 max_current_x = max (it->current_x, max_current_x);
10588 break;
10589 }
10590 }
10591 else if (BUFFERP (it->object)
10592 && (it->method == GET_FROM_BUFFER
10593 || it->method == GET_FROM_STRETCH)
10594 && IT_CHARPOS (*it) >= to_charpos
10595
10596
10597
10598
10599
10600 && !(it->bidi_p
10601 && it->bidi_it.scan_dir == -1))
10602 skip = MOVE_POS_MATCH_OR_ZV;
10603 else
10604 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10605
10606 switch (skip)
10607 {
10608 case MOVE_POS_MATCH_OR_ZV:
10609 max_current_x = max (it->current_x, max_current_x);
10610 reached = 8;
10611 goto out;
10612
10613 case MOVE_NEWLINE_OR_CR:
10614 max_current_x = max (it->current_x, max_current_x);
10615 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10616 it->override_ascent = -1;
10617 set_iterator_to_next (it, true);
10618 it->continuation_lines_width = 0;
10619 break;
10620
10621 case MOVE_LINE_TRUNCATED:
10622 max_current_x = it->last_visible_x;
10623 it->continuation_lines_width = 0;
10624 reseat_at_next_visible_line_start (it, false);
10625 if ((op & MOVE_TO_POS) != 0
10626 && (IT_CHARPOS (*it) > to_charpos
10627 || (IT_CHARPOS (*it) == to_charpos
10628
10629
10630 && to_charpos == ZV
10631 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10632
10633
10634
10635 && (it->sp == 0
10636 || (STRINGP (it->string)
10637 && (it->current.overlay_string_index < 0
10638 || (it->current.overlay_string_index >= 0
10639 && it->current.overlay_string_index
10640 >= it->n_overlay_strings - 1))
10641 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10642 {
10643 reached = 9;
10644 goto out;
10645 }
10646 break;
10647
10648 case MOVE_LINE_CONTINUED:
10649 max_current_x = it->last_visible_x;
10650
10651
10652
10653
10654 if (it->c == '\t')
10655 {
10656 it->continuation_lines_width += it->last_visible_x;
10657
10658
10659
10660 if (it->current_x != it->last_visible_x
10661 && (op & MOVE_TO_VPOS)
10662 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10663 {
10664 line_start_x = it->current_x + it->pixel_width
10665 - it->last_visible_x;
10666 if (FRAME_WINDOW_P (it->f))
10667 {
10668 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10669 struct font *face_font = face->font;
10670
10671
10672
10673
10674
10675
10676
10677 eassert (face_font);
10678 if (face_font)
10679 {
10680 if (line_start_x < face_font->space_width)
10681 line_start_x
10682 += it->tab_width * face_font->space_width;
10683 }
10684 }
10685 set_iterator_to_next (it, false);
10686 }
10687 }
10688 else
10689 {
10690
10691
10692
10693
10694
10695
10696
10697
10698 if (IT_CHARPOS (*it) == orig_charpos
10699 && it->method == orig_method
10700 && orig_method == GET_FROM_BUFFER)
10701 set_iterator_to_next (it, false);
10702 it->continuation_lines_width += it->current_x;
10703 }
10704 break;
10705
10706 default:
10707 emacs_abort ();
10708 }
10709
10710
10711 it->current_x = line_start_x;
10712 line_start_x = 0;
10713 it->hpos = 0;
10714 it->line_number_produced_p = false;
10715 it->current_y += it->max_ascent + it->max_descent;
10716 ++it->vpos;
10717 last_height = it->max_ascent + it->max_descent;
10718 it->max_ascent = it->max_descent = 0;
10719 }
10720
10721 out:
10722
10723
10724
10725
10726
10727
10728 if (!FRAME_WINDOW_P (it->f)
10729 && op & MOVE_TO_POS
10730 && IT_CHARPOS (*it) == to_charpos
10731 && it->what == IT_CHARACTER
10732 && it->nglyphs > 1
10733 && it->line_wrap == WINDOW_WRAP
10734 && it->current_x == it->last_visible_x - 1
10735 && it->c != '\n'
10736 && it->c != '\t'
10737 && it->w->window_end_valid
10738 && it->vpos < it->w->window_end_vpos)
10739 {
10740 it->continuation_lines_width += it->current_x;
10741 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10742 it->current_y += it->max_ascent + it->max_descent;
10743 ++it->vpos;
10744 last_height = it->max_ascent + it->max_descent;
10745 }
10746
10747 if (backup_data)
10748 bidi_unshelve_cache (backup_data, true);
10749
10750 move_trace ("move_it_to: reached %d\n", reached);
10751
10752 return max_current_x;
10753 }
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765 void
10766 move_it_vertically_backward (struct it *it, int dy)
10767 {
10768 int nlines, h;
10769 struct it it2, it3;
10770 void *it2data = NULL, *it3data = NULL;
10771 ptrdiff_t start_pos;
10772 int nchars_per_row
10773 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10774 ptrdiff_t pos_limit;
10775
10776 move_further_back:
10777 eassert (dy >= 0);
10778
10779 start_pos = IT_CHARPOS (*it);
10780
10781
10782 nlines = max (1, dy / default_line_pixel_height (it->w));
10783 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10784 pos_limit = BEGV;
10785 else
10786 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10787
10788
10789
10790
10791 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10792 back_to_previous_visible_line_start (it);
10793
10794
10795
10796
10797
10798 reseat_1 (it, it->current.pos, true);
10799
10800
10801 it->current_x = it->hpos = 0;
10802
10803 it->continuation_lines_width = 0;
10804
10805
10806
10807
10808
10809 SAVE_IT (it2, *it, it2data);
10810 it2.max_ascent = it2.max_descent = 0;
10811 do
10812 {
10813 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10814 MOVE_TO_POS | MOVE_TO_VPOS);
10815 }
10816 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10817
10818
10819
10820
10821
10822
10823 || (it2.method == GET_FROM_STRING
10824 && IT_CHARPOS (it2) == start_pos
10825 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10826 eassert (IT_CHARPOS (*it) >= BEGV);
10827 SAVE_IT (it3, it2, it3data);
10828
10829 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10830 eassert (IT_CHARPOS (*it) >= BEGV);
10831
10832
10833 h = it2.current_y - it->current_y;
10834
10835 nlines = it2.vpos - it->vpos;
10836
10837
10838
10839 it->vpos -= nlines;
10840 it->current_y -= h;
10841
10842 if (dy == 0)
10843 {
10844
10845
10846
10847 RESTORE_IT (it, it, it2data);
10848 if (nlines > 0)
10849 move_it_by_lines (it, nlines);
10850
10851
10852
10853
10854
10855
10856 if (it->bidi_p
10857 && !it->continuation_lines_width
10858 && !STRINGP (it->string)
10859 && IT_CHARPOS (*it) > BEGV
10860 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10861 {
10862 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10863
10864 dec_both (&cp, &bp);
10865 SET_WITH_NARROWED_BEGV (it, cp,
10866 find_newline_no_quit (cp, bp, -1, NULL),
10867 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10868 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10869 }
10870 bidi_unshelve_cache (it3data, true);
10871 }
10872 else
10873 {
10874
10875
10876 int target_y = it->current_y + h - dy;
10877 int y0 = it3.current_y;
10878 int y1;
10879 int line_height;
10880
10881 RESTORE_IT (&it3, &it3, it3data);
10882 y1 = line_bottom_y (&it3);
10883 line_height = y1 - y0;
10884 RESTORE_IT (it, it, it2data);
10885
10886
10887 if (target_y < it->current_y
10888
10889
10890
10891
10892 && (it->current_y - target_y
10893 > min (window_box_height (it->w), line_height * 2 / 3))
10894 && IT_CHARPOS (*it) > BEGV)
10895 {
10896 move_trace (" not far enough -> move_vert %d\n",
10897 target_y - it->current_y);
10898 dy = it->current_y - target_y;
10899 goto move_further_back;
10900 }
10901 else if (target_y >= it->current_y + line_height
10902 && IT_CHARPOS (*it) < ZV)
10903 {
10904
10905
10906
10907
10908
10909
10910
10911
10912 if (!FRAME_WINDOW_P (it->f))
10913 move_it_vertically (it, target_y - it->current_y);
10914 else
10915 {
10916 struct text_pos last_pos;
10917 int last_y, last_vpos;
10918 do
10919 {
10920 last_pos = it->current.pos;
10921 last_y = it->current_y;
10922 last_vpos = it->vpos;
10923 move_it_by_lines (it, 1);
10924 }
10925 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10926 if (it->current_y > target_y)
10927 {
10928 reseat (it, last_pos, true);
10929 it->current_y = last_y;
10930 it->vpos = last_vpos;
10931 }
10932 }
10933 }
10934 }
10935 }
10936
10937
10938
10939
10940
10941
10942 void
10943 move_it_vertically (struct it *it, int dy)
10944 {
10945 if (dy <= 0)
10946 move_it_vertically_backward (it, -dy);
10947 else
10948 {
10949 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10950 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10951 MOVE_TO_POS | MOVE_TO_Y);
10952 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10953
10954
10955
10956 if (IT_CHARPOS (*it) == ZV
10957 && ZV > BEGV
10958 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10959 move_it_by_lines (it, 0);
10960 }
10961 }
10962
10963
10964
10965
10966 void
10967 move_it_past_eol (struct it *it)
10968 {
10969 enum move_it_result rc;
10970
10971 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
10972 if (rc == MOVE_NEWLINE_OR_CR)
10973 set_iterator_to_next (it, false);
10974 }
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985 void
10986 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
10987 {
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005 if (dvpos == 0)
11006 {
11007
11008 move_it_vertically_backward (it, 0);
11009
11010 last_height = 0;
11011 }
11012 else if (dvpos > 0)
11013 {
11014 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11015 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11016 {
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11028 -1, -1, -1, MOVE_TO_POS);
11029 }
11030 }
11031 else
11032 {
11033 struct it it2;
11034 void *it2data = NULL;
11035 ptrdiff_t start_charpos, orig_charpos, i;
11036 int nchars_per_row
11037 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11038 bool hit_pos_limit = false;
11039 ptrdiff_t pos_limit;
11040
11041
11042
11043
11044 dvpos += it->vpos;
11045 orig_charpos = IT_CHARPOS (*it);
11046 move_it_vertically_backward (it, 0);
11047 dvpos -= it->vpos;
11048
11049
11050
11051 start_charpos = IT_CHARPOS (*it);
11052 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11053 pos_limit = BEGV;
11054 else
11055 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11056
11057 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11058 back_to_previous_visible_line_start (it);
11059 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11060 hit_pos_limit = true;
11061 reseat (it, it->current.pos, true);
11062
11063
11064 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11065 {
11066
11067 dvpos += it->vpos;
11068 move_it_vertically_backward (it, 0);
11069 dvpos -= it->vpos;
11070 if (IT_POS_VALID_AFTER_MOVE_P (it))
11071 break;
11072
11073
11074 back_to_previous_visible_line_start (it);
11075 reseat (it, it->current.pos, true);
11076 dvpos--;
11077 }
11078
11079 it->current_x = it->hpos = 0;
11080
11081
11082
11083 SAVE_IT (it2, *it, it2data);
11084 it2.vpos = it2.current_y = 0;
11085 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11086 it->vpos -= it2.vpos;
11087 it->current_y -= it2.current_y;
11088 it->current_x = it->hpos = 0;
11089
11090
11091 if (it2.vpos > -dvpos)
11092 {
11093 int delta = it2.vpos + dvpos;
11094
11095 RESTORE_IT (&it2, &it2, it2data);
11096 SAVE_IT (it2, *it, it2data);
11097 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11098
11099
11100 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11101 RESTORE_IT (it, &it2, it2data);
11102 else
11103 bidi_unshelve_cache (it2data, true);
11104 }
11105 else if (hit_pos_limit && pos_limit > BEGV
11106 && dvpos < 0 && it2.vpos < -dvpos)
11107 {
11108
11109
11110
11111
11112
11113
11114
11115
11116 dvpos += it2.vpos;
11117 RESTORE_IT (it, it, it2data);
11118 for (i = -dvpos; i > 0; --i)
11119 {
11120 back_to_previous_visible_line_start (it);
11121 it->vpos--;
11122 }
11123 reseat_1 (it, it->current.pos, true);
11124 }
11125 else
11126 RESTORE_IT (it, it, it2data);
11127 }
11128 }
11129
11130 int
11131 partial_line_height (struct it *it_origin)
11132 {
11133
11134
11135
11136
11137
11138 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11139 && it_origin->line_wrap == TRUNCATE)
11140 return 0;
11141
11142 int partial_height;
11143 void *it_data = NULL;
11144 struct it it;
11145 SAVE_IT (it, *it_origin, it_data);
11146 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11147 MOVE_TO_POS | MOVE_TO_Y);
11148 if (it.what == IT_EOB)
11149 {
11150 int vis_height = it.last_visible_y - it.current_y;
11151 int height = it.ascent + it.descent;
11152 partial_height = (vis_height < height) ? vis_height : 0;
11153 }
11154 else
11155 {
11156 int last_line_y = it.current_y;
11157 move_it_by_lines (&it, 1);
11158 partial_height = (it.current_y > it.last_visible_y)
11159 ? it.last_visible_y - last_line_y : 0;
11160 }
11161 RESTORE_IT (&it, &it, it_data);
11162 return partial_height;
11163 }
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176 static enum move_it_result
11177 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11178 {
11179 ptrdiff_t nl_bytepos;
11180 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11181 1, &nl_bytepos);
11182 struct text_pos new_pos;
11183 enum move_it_result move_result;
11184
11185 if (nl_pos - IT_CHARPOS (*it) > nchars)
11186 {
11187 SET_TEXT_POS (new_pos,
11188 IT_CHARPOS (*it) + nchars,
11189 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11190 move_result = MOVE_X_REACHED;
11191 }
11192 else
11193 {
11194 if (nl_bytepos < ZV_BYTE
11195 || (nl_bytepos > BEGV_BYTE
11196 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11197 {
11198 nl_pos--;
11199 nl_bytepos--;
11200 move_result = MOVE_NEWLINE_OR_CR;
11201 }
11202 else
11203 move_result = MOVE_POS_MATCH_OR_ZV;
11204 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11205 }
11206 reseat (it, new_pos, false);
11207 return move_result;
11208 }
11209
11210
11211
11212 bool
11213 in_display_vector_p (struct it *it)
11214 {
11215 return (it->method == GET_FROM_DISPLAY_VECTOR
11216 && it->current.dpvec_index > 0
11217 && it->dpvec + it->current.dpvec_index != it->dpend);
11218 }
11219
11220
11221
11222
11223
11224 static Lisp_Object
11225 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11226 Lisp_Object x_limit, Lisp_Object y_limit,
11227 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11228 {
11229 struct window *w = decode_live_window (window);
11230 struct it it;
11231 ptrdiff_t start, end, bpos;
11232 struct text_pos startp;
11233 void *itdata = NULL;
11234 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11235
11236 if (NILP (from))
11237 {
11238 start = BEGV;
11239 bpos = BEGV_BYTE;
11240 }
11241 else if (EQ (from, Qt))
11242 {
11243 start = BEGV;
11244 bpos = BEGV_BYTE;
11245 while (bpos < ZV_BYTE)
11246 {
11247 c = FETCH_BYTE (bpos);
11248 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11249 break;
11250 inc_both (&start, &bpos);
11251 }
11252 while (bpos > BEGV_BYTE)
11253 {
11254 dec_both (&start, &bpos);
11255 c = FETCH_BYTE (bpos);
11256 if (!(c == ' ' || c == '\t'))
11257 break;
11258 }
11259 }
11260 else if (CONSP (from))
11261 {
11262 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11263 bpos = CHAR_TO_BYTE (start);
11264 CHECK_FIXNUM (XCDR (from));
11265 vertical_offset = XFIXNUM (XCDR (from));
11266 }
11267 else
11268 {
11269 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11270 bpos = CHAR_TO_BYTE (start);
11271 }
11272
11273 SET_TEXT_POS (startp, start, bpos);
11274
11275 if (NILP (to))
11276 end = ZV;
11277 else if (EQ (to, Qt))
11278 {
11279 end = ZV;
11280 bpos = ZV_BYTE;
11281 while (bpos > BEGV_BYTE)
11282 {
11283 dec_both (&end, &bpos);
11284 c = FETCH_BYTE (bpos);
11285 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11286 {
11287 inc_both (&end, &bpos);
11288 break;
11289 }
11290 }
11291 while (bpos < ZV_BYTE)
11292 {
11293 c = fetch_char_advance (&end, &bpos);
11294 if (!(c == ' ' || c == '\t'))
11295 break;
11296 }
11297 }
11298 else
11299 end = clip_to_bounds (start, fix_position (to), ZV);
11300
11301 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11302 max_x = XFIXNUM (x_limit);
11303 else if (!NILP (x_limit))
11304 max_x = INT_MAX;
11305
11306 if (NILP (y_limit))
11307 max_y = INT_MAX;
11308 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11309 max_y = XFIXNUM (y_limit);
11310
11311 itdata = bidi_shelve_cache ();
11312
11313 start_display (&it, w, startp);
11314
11315 int start_y = it.current_y;
11316
11317
11318
11319
11320
11321
11322
11323 it.bidi_p = false;
11324
11325 int start_x;
11326 if (vertical_offset != 0)
11327 {
11328 int last_y;
11329 it.current_y = 0;
11330
11331 move_it_by_lines (&it, 0);
11332
11333
11334
11335
11336
11337 if (vertical_offset < 0)
11338 {
11339 while (it.current_y > vertical_offset)
11340 {
11341 last_y = it.current_y;
11342 move_it_vertically_backward (&it,
11343 (abs (vertical_offset)
11344 + it.current_y));
11345
11346 if (it.current_y == last_y)
11347 break;
11348 }
11349 }
11350 else
11351 {
11352 move_it_vertically (&it, vertical_offset);
11353 }
11354
11355 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11356 + WINDOW_HEADER_LINE_HEIGHT (w));
11357 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11358 start_y = it.current_y;
11359 start_x = it.current_x;
11360 }
11361 else
11362 {
11363
11364
11365
11366 reseat_at_previous_visible_line_start (&it);
11367 it.current_x = it.hpos = 0;
11368 if (IT_CHARPOS (it) != start)
11369 {
11370 void *it1data = NULL;
11371 struct it it1;
11372
11373 SAVE_IT (it1, it, it1data);
11374 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11375
11376
11377
11378
11379
11380 if (IT_CHARPOS (it) > start && start > BEGV)
11381 {
11382 ptrdiff_t it1pos = IT_CHARPOS (it1);
11383 int it1_x = it1.current_x;
11384
11385 RESTORE_IT (&it, &it1, it1data);
11386
11387
11388
11389
11390
11391 if (start - 1 > it1pos)
11392 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11393 else
11394 move_it_in_display_line (&it, start, it1_x + 1,
11395 MOVE_TO_POS | MOVE_TO_X);
11396 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11397 start_x = it.current_x;
11398
11399
11400
11401 if (IT_CHARPOS (it) == start - 1)
11402 start_x += it.pixel_width;
11403 }
11404 else
11405 {
11406 start_x = it.current_x;
11407 bidi_unshelve_cache (it1data, true);
11408 }
11409 }
11410 else
11411 start_x = it.current_x;
11412 }
11413
11414
11415 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11416 int to_x = -1;
11417 it.current_y = start_y;
11418
11419
11420 if (FETCH_BYTE (start) == '\n')
11421 it.current_x = 0;
11422 if (!NILP (x_limit))
11423 {
11424 it.last_visible_x = max_x;
11425
11426
11427
11428 move_op |= MOVE_TO_X;
11429 to_x = INT_MAX;
11430 }
11431
11432 void *it2data = NULL;
11433 struct it it2;
11434 SAVE_IT (it2, it, it2data);
11435
11436 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11437
11438
11439
11440
11441
11442 if (IT_CHARPOS (it) > end)
11443 {
11444 end--;
11445 RESTORE_IT (&it, &it2, it2data);
11446 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11447
11448
11449
11450 if (IT_CHARPOS (it) == end)
11451 {
11452 x += it.pixel_width;
11453
11454
11455 if (!NILP (ignore_line_at_end))
11456 doff = (max (it.max_ascent, it.ascent)
11457 + max (it.max_descent, it.descent));
11458 else
11459 {
11460 it.max_ascent = max (it.max_ascent, it.ascent);
11461 it.max_descent = max (it.max_descent, it.descent);
11462 }
11463 }
11464 }
11465 else
11466 bidi_unshelve_cache (it2data, true);
11467
11468 if (!NILP (x_limit))
11469 {
11470
11471 if (x > max_x)
11472 x = max_x;
11473 }
11474
11475
11476
11477
11478 if (it.current_y > start_y)
11479 start_x = 0;
11480
11481
11482
11483 if (!NILP (ignore_line_at_end))
11484 y = (it.current_y + doff
11485 - WINDOW_TAB_LINE_HEIGHT (w)
11486 - WINDOW_HEADER_LINE_HEIGHT (w));
11487 else
11488 y = (it.current_y + it.max_ascent + it.max_descent + doff
11489 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11490
11491
11492 if (y > max_y)
11493 y = max_y;
11494
11495 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11496 && window_wants_tab_line (w))
11497
11498 {
11499 Lisp_Object window_tab_line_format
11500 = window_parameter (w, Qtab_line_format);
11501
11502 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11503 NILP (window_tab_line_format)
11504 ? BVAR (current_buffer, tab_line_format)
11505 : window_tab_line_format);
11506 }
11507
11508 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11509 && window_wants_header_line (w))
11510 {
11511 Lisp_Object window_header_line_format
11512 = window_parameter (w, Qheader_line_format);
11513
11514 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11515 NILP (window_header_line_format)
11516 ? BVAR (current_buffer, header_line_format)
11517 : window_header_line_format);
11518 }
11519
11520 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11521 && window_wants_mode_line (w))
11522 {
11523 Lisp_Object window_mode_line_format
11524 = window_parameter (w, Qmode_line_format);
11525
11526 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11527 NILP (window_mode_line_format)
11528 ? BVAR (current_buffer, mode_line_format)
11529 : window_mode_line_format);
11530 }
11531
11532 bidi_unshelve_cache (itdata, false);
11533
11534 return (!vertical_offset
11535 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11536 : list3i (x - start_x, y, start));
11537 }
11538
11539 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11540 doc:
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595 )
11596 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11597 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11598 {
11599 struct window *w = decode_live_window (window);
11600 struct buffer *b = XBUFFER (w->contents);
11601 struct buffer *old_b = NULL;
11602 Lisp_Object value;
11603
11604 if (b != current_buffer)
11605 {
11606 old_b = current_buffer;
11607 set_buffer_internal_1 (b);
11608 }
11609
11610 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11611 ignore_line_at_end);
11612
11613 if (old_b)
11614 set_buffer_internal_1 (old_b);
11615
11616 return value;
11617 }
11618
11619 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11620 doc:
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633 )
11634 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11635 Lisp_Object y_limit)
11636 {
11637 struct window *w = decode_live_window (window);
11638 struct buffer *b = (NILP (buffer_or_name)
11639 ? current_buffer
11640 : XBUFFER (Fget_buffer (buffer_or_name)));
11641 Lisp_Object buffer, value;
11642 specpdl_ref count = SPECPDL_INDEX ();
11643
11644 XSETBUFFER (buffer, b);
11645
11646
11647
11648
11649 record_unwind_protect (unwind_with_echo_area_buffer,
11650 with_echo_area_buffer_unwind_data (w));
11651
11652 set_buffer_internal_1 (b);
11653
11654 ptrdiff_t base_line_pos = w->base_line_pos;
11655 int end_valid = w->window_end_valid;
11656 if (!EQ (buffer, w->contents))
11657 {
11658 wset_buffer (w, buffer);
11659 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11660 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11661 }
11662
11663 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11664 Qnil);
11665
11666 unbind_to (count, Qnil);
11667
11668
11669
11670 w->base_line_pos = base_line_pos;
11671 w->window_end_valid = end_valid;
11672
11673 return value;
11674 }
11675
11676
11677 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11678 Sdisplay__line_is_continued_p, 0, 0, 0,
11679 doc: )
11680 (void)
11681 {
11682 struct buffer *oldb = current_buffer;
11683 struct window *w = XWINDOW (selected_window);
11684 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11685
11686 set_buffer_internal_1 (XBUFFER (w->contents));
11687
11688 if (PT < ZV)
11689 {
11690 struct text_pos startpos;
11691 struct it it;
11692 void *itdata;
11693
11694
11695 Lisp_Object opoint = Fpoint_marker ();
11696
11697
11698
11699 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11700 SET_TEXT_POS (startpos, PT, PT_BYTE);
11701 itdata = bidi_shelve_cache ();
11702 start_display (&it, w, startpos);
11703
11704 if (it.line_wrap != TRUNCATE)
11705 {
11706 it.glyph_row = NULL;
11707 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11708 }
11709 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11710 bidi_unshelve_cache (itdata, false);
11711 }
11712 set_buffer_internal_1 (oldb);
11713
11714 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11715 }
11716
11717
11718
11719
11720
11721
11722
11723
11724 static ptrdiff_t
11725 format_nargs (char const *format)
11726 {
11727 ptrdiff_t nargs = 0;
11728 for (char const *p = format; (p = strchr (p, '%')); p++)
11729 if (p[1] == '%')
11730 p++;
11731 else
11732 nargs++;
11733 return nargs;
11734 }
11735
11736
11737
11738
11739 void
11740 add_to_log (const char *format, ...)
11741 {
11742 va_list ap;
11743 va_start (ap, format);
11744 vadd_to_log (format, ap);
11745 va_end (ap);
11746 }
11747
11748 void
11749 vadd_to_log (char const *format, va_list ap)
11750 {
11751 ptrdiff_t form_nargs = format_nargs (format);
11752 ptrdiff_t nargs = 1 + form_nargs;
11753 Lisp_Object args[10];
11754 eassert (nargs <= ARRAYELTS (args));
11755 AUTO_STRING (args0, format);
11756 args[0] = args0;
11757 for (ptrdiff_t i = 1; i <= nargs; i++)
11758 args[i] = va_arg (ap, Lisp_Object);
11759 Lisp_Object msg = Qnil;
11760 msg = Fformat_message (nargs, args);
11761
11762 ptrdiff_t len = SBYTES (msg) + 1;
11763 USE_SAFE_ALLOCA;
11764 char *buffer = SAFE_ALLOCA (len);
11765 memcpy (buffer, SDATA (msg), len);
11766
11767 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11768 SAFE_FREE ();
11769 }
11770
11771
11772
11773
11774 void
11775 message_log_maybe_newline (void)
11776 {
11777 if (message_log_need_newline)
11778 message_dolog ("", 0, true, false);
11779 }
11780
11781
11782
11783
11784
11785
11786
11787
11788
11789
11790
11791 void
11792 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11793 {
11794 const unsigned char *msg = (const unsigned char *) m;
11795
11796 if (!NILP (Vmemory_full))
11797 return;
11798
11799 if (!NILP (Vmessage_log_max))
11800 {
11801 struct buffer *oldbuf;
11802 Lisp_Object oldpoint, oldbegv, oldzv;
11803 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11804 ptrdiff_t point_at_end = 0;
11805 ptrdiff_t zv_at_end = 0;
11806 Lisp_Object old_deactivate_mark;
11807
11808 old_deactivate_mark = Vdeactivate_mark;
11809 oldbuf = current_buffer;
11810
11811
11812
11813 if (! STRINGP (Vmessages_buffer_name))
11814 Vmessages_buffer_name = build_string ("*Messages*");
11815
11816
11817 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11818 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11819 if (newbuffer
11820 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11821 call0 (intern ("messages-buffer-mode"));
11822
11823 bset_undo_list (current_buffer, Qt);
11824 bset_cache_long_scans (current_buffer, Qnil);
11825
11826 oldpoint = message_dolog_marker1;
11827 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11828 oldbegv = message_dolog_marker2;
11829 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11830 oldzv = message_dolog_marker3;
11831 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11832
11833 if (PT == Z)
11834 point_at_end = 1;
11835 if (ZV == Z)
11836 zv_at_end = 1;
11837
11838 BEGV = BEG;
11839 BEGV_BYTE = BEG_BYTE;
11840 ZV = Z;
11841 ZV_BYTE = Z_BYTE;
11842 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11843
11844
11845
11846 if (multibyte
11847 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11848 {
11849
11850
11851 for (ptrdiff_t i = 0; i < nbytes; )
11852 {
11853 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11854 char work = CHAR_TO_BYTE8 (c);
11855 insert_1_both (&work, 1, 1, true, false, false);
11856 i += char_bytes;
11857 }
11858 }
11859 else if (! multibyte
11860 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11861 {
11862
11863
11864 for (ptrdiff_t i = 0; i < nbytes; i++)
11865 {
11866 int c = make_char_multibyte (msg[i]);
11867 unsigned char str[MAX_MULTIBYTE_LENGTH];
11868 int char_bytes = CHAR_STRING (c, str);
11869 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11870 }
11871 }
11872 else if (nbytes)
11873 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11874 true, false, false);
11875
11876 if (nlflag)
11877 {
11878 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11879 intmax_t dups;
11880
11881
11882
11883
11884
11885 specpdl_ref count = SPECPDL_INDEX ();
11886 specbind (Qinhibit_modification_hooks, Qt);
11887
11888 insert_1_both ("\n", 1, 1, true, false, false);
11889
11890 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11891 this_bol = PT;
11892 this_bol_byte = PT_BYTE;
11893
11894
11895
11896 if (this_bol > BEG)
11897 {
11898 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11899 prev_bol = PT;
11900 prev_bol_byte = PT_BYTE;
11901
11902 dups = message_log_check_duplicate (prev_bol_byte,
11903 this_bol_byte);
11904 if (dups)
11905 {
11906 del_range_both (prev_bol, prev_bol_byte,
11907 this_bol, this_bol_byte, false);
11908 if (dups > 1)
11909 {
11910 char dupstr[sizeof " [ times]"
11911 + INT_STRLEN_BOUND (dups)];
11912
11913
11914
11915 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11916 dups);
11917 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11918 insert_1_both (dupstr, duplen, duplen,
11919 true, false, true);
11920 }
11921 }
11922 }
11923
11924
11925
11926
11927
11928 if (FIXNATP (Vmessage_log_max))
11929 {
11930 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11931 -XFIXNAT (Vmessage_log_max) - 1, false);
11932 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11933 }
11934
11935 unbind_to (count, Qnil);
11936 }
11937 BEGV = marker_position (oldbegv);
11938 BEGV_BYTE = marker_byte_position (oldbegv);
11939
11940 if (zv_at_end)
11941 {
11942 ZV = Z;
11943 ZV_BYTE = Z_BYTE;
11944 }
11945 else
11946 {
11947 ZV = marker_position (oldzv);
11948 ZV_BYTE = marker_byte_position (oldzv);
11949 }
11950
11951 if (point_at_end)
11952 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11953 else
11954
11955
11956 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11957 marker_byte_position (oldpoint));
11958
11959 unchain_marker (XMARKER (oldpoint));
11960 unchain_marker (XMARKER (oldbegv));
11961 unchain_marker (XMARKER (oldzv));
11962
11963
11964
11965
11966
11967
11968
11969 windows_or_buffers_changed = old_windows_or_buffers_changed;
11970 bset_redisplay (current_buffer);
11971
11972 set_buffer_internal (oldbuf);
11973
11974 message_log_need_newline = !nlflag;
11975 Vdeactivate_mark = old_deactivate_mark;
11976 }
11977 }
11978
11979
11980
11981
11982
11983
11984
11985
11986 static intmax_t
11987 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
11988 {
11989 ptrdiff_t i;
11990 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
11991 bool seen_dots = false;
11992 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
11993 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
11994
11995 for (i = 0; i < len; i++)
11996 {
11997 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
11998 seen_dots = true;
11999 if (p1[i] != p2[i])
12000 return seen_dots;
12001 }
12002 p1 += len;
12003 if (*p1 == '\n')
12004 return 2;
12005 if (*p1++ == ' ' && *p1++ == '[')
12006 {
12007 char *pend;
12008 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12009 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12010 return n + 1;
12011 }
12012 return 0;
12013 }
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023 void
12024 message3 (Lisp_Object m)
12025 {
12026 clear_message (true, true);
12027 cancel_echoing ();
12028
12029
12030 message_log_maybe_newline ();
12031 if (STRINGP (m))
12032 {
12033 ptrdiff_t nbytes = SBYTES (m);
12034 bool multibyte = STRING_MULTIBYTE (m);
12035 char *buffer;
12036 USE_SAFE_ALLOCA;
12037 SAFE_ALLOCA_STRING (buffer, m);
12038 message_dolog (buffer, nbytes, true, multibyte);
12039 SAFE_FREE ();
12040 }
12041 if (! inhibit_message)
12042 message3_nolog (m);
12043 }
12044
12045
12046
12047 static void
12048 message_to_stderr (Lisp_Object m)
12049 {
12050 if (noninteractive_need_newline)
12051 {
12052 noninteractive_need_newline = false;
12053 errputc ('\n');
12054 }
12055 if (STRINGP (m))
12056 {
12057 Lisp_Object coding_system = Vlocale_coding_system;
12058 Lisp_Object s;
12059
12060 if (!NILP (Vcoding_system_for_write))
12061 coding_system = Vcoding_system_for_write;
12062 if (!NILP (coding_system))
12063 s = code_convert_string_norecord (m, coding_system, true);
12064 else
12065 s = m;
12066
12067 errwrite (SDATA (s), SBYTES (s));
12068 }
12069 if (STRINGP (m) || !cursor_in_echo_area)
12070 errputc ('\n');
12071 }
12072
12073
12074
12075
12076
12077
12078 void
12079 message3_nolog (Lisp_Object m)
12080 {
12081 struct frame *sf = SELECTED_FRAME ();
12082
12083 if (FRAME_INITIAL_P (sf))
12084 message_to_stderr (m);
12085
12086
12087
12088 else if (INTERACTIVE && sf->glyphs_initialized_p)
12089 {
12090
12091
12092 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12093 Lisp_Object frame = XWINDOW (mini_window)->frame;
12094 struct frame *f = XFRAME (frame);
12095
12096 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12097 Fmake_frame_visible (frame);
12098
12099 if (STRINGP (m) && SCHARS (m) > 0)
12100 {
12101 set_message (m);
12102 if (minibuffer_auto_raise)
12103 Fraise_frame (frame);
12104
12105
12106 echo_message_buffer = Qnil;
12107 }
12108 else
12109 clear_message (true, true);
12110
12111 do_pending_window_change (false);
12112 echo_area_display (true);
12113 do_pending_window_change (false);
12114 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12115 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12116 }
12117 }
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128 void
12129 message1 (const char *m)
12130 {
12131 message3 (m ? build_unibyte_string (m) : Qnil);
12132 }
12133
12134
12135
12136
12137 void
12138 message1_nolog (const char *m)
12139 {
12140 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12141 }
12142
12143
12144
12145
12146 void
12147 message_with_string (const char *m, Lisp_Object string, bool log)
12148 {
12149 CHECK_STRING (string);
12150
12151 bool need_message;
12152 if (noninteractive)
12153 need_message = !!m;
12154 else if (!INTERACTIVE)
12155 need_message = false;
12156 else
12157 {
12158
12159
12160
12161 Lisp_Object mini_window;
12162 struct frame *f, *sf = SELECTED_FRAME ();
12163
12164
12165
12166 mini_window = FRAME_MINIBUF_WINDOW (sf);
12167 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12168
12169
12170
12171
12172 need_message = f->glyphs_initialized_p;
12173 }
12174
12175 if (need_message)
12176 {
12177 AUTO_STRING (fmt, m);
12178 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12179
12180 if (noninteractive)
12181 message_to_stderr (msg);
12182 else
12183 {
12184 if (log)
12185 message3 (msg);
12186 else
12187 message3_nolog (msg);
12188
12189
12190
12191 message_buf_print = false;
12192 }
12193 }
12194 }
12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12208 vmessage (const char *m, va_list ap)
12209 {
12210 if (noninteractive)
12211 {
12212 if (m)
12213 {
12214 if (noninteractive_need_newline)
12215 putc ('\n', stderr);
12216 noninteractive_need_newline = false;
12217 vfprintf (stderr, m, ap);
12218 if (!cursor_in_echo_area)
12219 putc ('\n', stderr);
12220 fflush (stderr);
12221 }
12222 }
12223 else if (INTERACTIVE)
12224 {
12225
12226
12227
12228 Lisp_Object mini_window;
12229 struct frame *f, *sf = SELECTED_FRAME ();
12230
12231
12232
12233 mini_window = FRAME_MINIBUF_WINDOW (sf);
12234 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12235
12236
12237
12238
12239 if (f->glyphs_initialized_p)
12240 {
12241 if (m)
12242 {
12243 ptrdiff_t len;
12244 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12245 USE_SAFE_ALLOCA;
12246 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12247
12248 len = doprnt (message_buf, maxsize, m, 0, ap);
12249
12250 message3 (make_string (message_buf, len));
12251 SAFE_FREE ();
12252 }
12253 else
12254 message1 (0);
12255
12256
12257
12258 message_buf_print = false;
12259 }
12260 }
12261 }
12262
12263
12264 void
12265 message (const char *m, ...)
12266 {
12267 va_list ap;
12268 va_start (ap, m);
12269 vmessage (m, ap);
12270 va_end (ap);
12271 }
12272
12273
12274
12275
12276
12277
12278 void
12279 update_echo_area (void)
12280 {
12281 if (!NILP (echo_area_buffer[0]))
12282 {
12283 Lisp_Object string;
12284 string = Fcurrent_message ();
12285 message3 (string);
12286 }
12287 }
12288
12289
12290
12291
12292
12293 static void
12294 ensure_echo_area_buffers (void)
12295 {
12296 for (int i = 0; i < 2; i++)
12297 if (!BUFFERP (echo_buffer[i])
12298 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12299 {
12300 Lisp_Object old_buffer = echo_buffer[i];
12301 static char const name_fmt[] = " *Echo Area %d*";
12302 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12303 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12304 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12305 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12306
12307
12308
12309
12310 for (int j = 0; j < 2; j++)
12311 if (EQ (old_buffer, echo_area_buffer[j]))
12312 echo_area_buffer[j] = echo_buffer[i];
12313 }
12314 }
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333 static bool
12334 with_echo_area_buffer (struct window *w, int which,
12335 bool (*fn) (void *, Lisp_Object),
12336 void *a1, Lisp_Object a2)
12337 {
12338 Lisp_Object buffer;
12339 bool this_one, the_other, clear_buffer_p, rc;
12340 specpdl_ref count = SPECPDL_INDEX ();
12341
12342
12343 ensure_echo_area_buffers ();
12344
12345 clear_buffer_p = false;
12346
12347 if (which == 0)
12348 this_one = false, the_other = true;
12349 else if (which > 0)
12350 this_one = true, the_other = false;
12351 else
12352 {
12353 this_one = false, the_other = true;
12354 clear_buffer_p = true;
12355
12356
12357
12358 if (!NILP (echo_area_buffer[this_one])
12359 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12360 echo_area_buffer[this_one] = Qnil;
12361 }
12362
12363
12364
12365 if (NILP (echo_area_buffer[this_one]))
12366 {
12367 echo_area_buffer[this_one]
12368 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12369 ? echo_buffer[the_other]
12370 : echo_buffer[this_one]);
12371 clear_buffer_p = true;
12372 }
12373
12374 buffer = echo_area_buffer[this_one];
12375
12376
12377
12378 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12379 cancel_echoing ();
12380
12381 record_unwind_protect (unwind_with_echo_area_buffer,
12382 with_echo_area_buffer_unwind_data (w));
12383
12384
12385
12386
12387
12388
12389
12390
12391 set_buffer_internal_1 (XBUFFER (buffer));
12392 if (w)
12393 {
12394 wset_buffer (w, buffer);
12395 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12396 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12397 }
12398
12399 bset_undo_list (current_buffer, Qt);
12400 bset_read_only (current_buffer, Qnil);
12401 specbind (Qinhibit_read_only, Qt);
12402 specbind (Qinhibit_modification_hooks, Qt);
12403
12404 if (clear_buffer_p && Z > BEG)
12405 del_range (BEG, Z);
12406
12407 eassert (BEGV >= BEG);
12408 eassert (ZV <= Z && ZV >= BEGV);
12409
12410 rc = fn (a1, a2);
12411
12412 eassert (BEGV >= BEG);
12413 eassert (ZV <= Z && ZV >= BEGV);
12414
12415 unbind_to (count, Qnil);
12416 return rc;
12417 }
12418
12419
12420
12421
12422
12423 static Lisp_Object
12424 with_echo_area_buffer_unwind_data (struct window *w)
12425 {
12426 int i = 0;
12427 Lisp_Object vector, tmp;
12428
12429
12430
12431 vector = Vwith_echo_area_save_vector;
12432 Vwith_echo_area_save_vector = Qnil;
12433
12434 if (NILP (vector))
12435 vector = make_nil_vector (11);
12436
12437 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12438 ASET (vector, i, Vdeactivate_mark); ++i;
12439 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12440
12441 if (w)
12442 {
12443 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12444 ASET (vector, i, w->contents); ++i;
12445 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12446 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12447 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12448 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12449 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12450 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12451 }
12452 else
12453 {
12454 int end = i + 8;
12455 for (; i < end; ++i)
12456 ASET (vector, i, Qnil);
12457 }
12458
12459 eassert (i == ASIZE (vector));
12460 return vector;
12461 }
12462
12463
12464
12465
12466
12467 static void
12468 unwind_with_echo_area_buffer (Lisp_Object vector)
12469 {
12470 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12471 Vdeactivate_mark = AREF (vector, 1);
12472 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12473
12474 if (WINDOWP (AREF (vector, 3)))
12475 {
12476 struct window *w;
12477 Lisp_Object buffer;
12478
12479 w = XWINDOW (AREF (vector, 3));
12480 buffer = AREF (vector, 4);
12481
12482 wset_buffer (w, buffer);
12483 set_marker_restricted_both (w->pointm, buffer,
12484 XFIXNAT (AREF (vector, 5)),
12485 XFIXNAT (AREF (vector, 6)));
12486 set_marker_restricted_both (w->old_pointm, buffer,
12487 XFIXNAT (AREF (vector, 7)),
12488 XFIXNAT (AREF (vector, 8)));
12489 set_marker_restricted_both (w->start, buffer,
12490 XFIXNAT (AREF (vector, 9)),
12491 XFIXNAT (AREF (vector, 10)));
12492 }
12493
12494 Vwith_echo_area_save_vector = vector;
12495 }
12496
12497
12498
12499
12500
12501 void
12502 setup_echo_area_for_printing (bool multibyte_p)
12503 {
12504
12505 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12506 Fkill_emacs (Qnil, Qnil);
12507
12508 ensure_echo_area_buffers ();
12509
12510 if (!message_buf_print)
12511 {
12512
12513
12514 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12515 echo_area_buffer[0] = echo_buffer[1];
12516 else
12517 echo_area_buffer[0] = echo_buffer[0];
12518
12519
12520 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12521 bset_truncate_lines (current_buffer, Qnil);
12522
12523 if (Z > BEG)
12524 {
12525 specpdl_ref count = SPECPDL_INDEX ();
12526 specbind (Qinhibit_read_only, Qt);
12527
12528 del_range (BEG, Z);
12529 unbind_to (count, Qnil);
12530 }
12531 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12532
12533
12534
12535
12536
12537
12538
12539 if (unibyte_display_via_language_environment
12540 && !multibyte_p
12541 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12542 Fset_buffer_multibyte (Qnil);
12543 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12544 Fset_buffer_multibyte (Qt);
12545
12546
12547 if (minibuffer_auto_raise)
12548 {
12549 struct frame *sf = SELECTED_FRAME ();
12550 Lisp_Object mini_window;
12551 mini_window = FRAME_MINIBUF_WINDOW (sf);
12552 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12553 }
12554
12555 message_log_maybe_newline ();
12556 message_buf_print = true;
12557 }
12558 else
12559 {
12560 if (NILP (echo_area_buffer[0]))
12561 {
12562 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12563 echo_area_buffer[0] = echo_buffer[1];
12564 else
12565 echo_area_buffer[0] = echo_buffer[0];
12566 }
12567
12568 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12569 {
12570
12571 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12572 bset_truncate_lines (current_buffer, Qnil);
12573 }
12574 }
12575 }
12576
12577
12578
12579
12580
12581
12582
12583 static bool
12584 display_echo_area (struct window *w)
12585 {
12586 bool no_message_p, window_height_changed_p;
12587
12588
12589
12590
12591
12592
12593 specpdl_ref count = inhibit_garbage_collection ();
12594
12595
12596
12597
12598
12599 bool i = display_last_displayed_message_p;
12600
12601
12602
12603 no_message_p = NILP (echo_area_buffer[i]);
12604
12605 window_height_changed_p
12606 = with_echo_area_buffer (w, display_last_displayed_message_p,
12607 display_echo_area_1, w, Qnil);
12608
12609 if (no_message_p)
12610 echo_area_buffer[i] = Qnil;
12611
12612 unbind_to (count, Qnil);
12613 return window_height_changed_p;
12614 }
12615
12616
12617
12618
12619
12620
12621
12622
12623 static bool
12624 display_echo_area_1 (void *a1, Lisp_Object a2)
12625 {
12626 struct window *w = a1;
12627 Lisp_Object window;
12628 struct text_pos start;
12629
12630
12631
12632
12633 forget_escape_and_glyphless_faces ();
12634
12635
12636
12637
12638 bool window_height_changed_p = resize_mini_window (w, false);
12639
12640
12641 SET_TEXT_POS_FROM_MARKER (start, w->start);
12642
12643
12644 clear_glyph_matrix (w->desired_matrix);
12645 XSETWINDOW (window, w);
12646 void *itdata = bidi_shelve_cache ();
12647 try_window (window, start, 0);
12648 bidi_unshelve_cache (itdata, false);
12649
12650 return window_height_changed_p;
12651 }
12652
12653
12654
12655
12656
12657
12658 void
12659 resize_echo_area_exactly (void)
12660 {
12661 if (BUFFERP (echo_area_buffer[0])
12662 && WINDOWP (echo_area_window))
12663 {
12664 struct window *w = XWINDOW (echo_area_window);
12665 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12666 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12667 w, resize_exactly);
12668 if (resized_p)
12669 {
12670 windows_or_buffers_changed = 42;
12671 update_mode_lines = 30;
12672 redisplay_internal ();
12673 }
12674 }
12675 }
12676
12677
12678
12679
12680
12681
12682
12683
12684 static bool
12685 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12686 {
12687 return resize_mini_window (a1, !NILP (exactly));
12688 }
12689
12690
12691
12692
12693
12694
12695
12696
12697
12698
12699
12700
12701
12702 bool
12703 resize_mini_window (struct window *w, bool exact_p)
12704 {
12705 struct frame *f = XFRAME (w->frame);
12706 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12707
12708 eassert (MINI_WINDOW_P (w));
12709
12710
12711
12712
12713
12714
12715
12716 if (!NILP (Vinhibit_redisplay))
12717 return false;
12718
12719
12720 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12721 set_marker_both (w->start, w->contents,
12722 BUF_BEGV (XBUFFER (w->contents)),
12723 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12724
12725
12726 if ((NILP (Vresize_mini_windows)
12727 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12728 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12729 return false;
12730
12731 if (FRAME_MINIBUF_ONLY_P (f))
12732 {
12733 if (!NILP (resize_mini_frames))
12734 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12735 }
12736 else
12737 {
12738 struct it it;
12739 int unit = FRAME_LINE_HEIGHT (f);
12740 int height, max_height;
12741 struct text_pos start;
12742 struct buffer *old_current_buffer = NULL;
12743 int windows_height = FRAME_INNER_HEIGHT (f);
12744
12745 if (current_buffer != XBUFFER (w->contents))
12746 {
12747 old_current_buffer = current_buffer;
12748 set_buffer_internal (XBUFFER (w->contents));
12749 }
12750
12751 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12752
12753
12754 if (FLOATP (Vmax_mini_window_height))
12755 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12756 else if (FIXNUMP (Vmax_mini_window_height))
12757 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12758 else
12759 max_height = windows_height / 4;
12760
12761
12762 max_height = clip_to_bounds (unit, max_height, windows_height);
12763
12764
12765 last_height = 0;
12766 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12767
12768
12769 if (it.max_ascent == 0 && it.max_descent == 0)
12770 {
12771 height = it.current_y;
12772
12773
12774
12775
12776
12777 if (!(it.line_wrap == TRUNCATE
12778 && it.current_x <= it.first_visible_x
12779 && ZV_BYTE > 1
12780 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12781 height += last_height;
12782 }
12783 else
12784 height = it.current_y + it.max_ascent + it.max_descent;
12785 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12786
12787
12788 if (height > max_height)
12789 {
12790 height = (max_height / unit) * unit;
12791 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12792 {
12793 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12794 move_it_vertically_backward (&it, height - unit);
12795
12796
12797
12798
12799
12800
12801
12802
12803
12804 move_it_by_lines (&it, 0);
12805 start = it.current.pos;
12806
12807
12808 w->start_at_line_beg = false;
12809 SET_MARKER_FROM_TEXT_POS (w->start, start);
12810 }
12811 }
12812 else
12813 {
12814 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12815 SET_MARKER_FROM_TEXT_POS (w->start, start);
12816 }
12817
12818 if (EQ (Vresize_mini_windows, Qgrow_only))
12819 {
12820
12821
12822 if (height > old_height)
12823 grow_mini_window (w, height - old_height);
12824 else if (height < old_height && (exact_p || BEGV == ZV))
12825 shrink_mini_window (w);
12826 }
12827 else if (height != old_height)
12828
12829 grow_mini_window (w, height - old_height);
12830
12831 if (old_current_buffer)
12832 set_buffer_internal (old_current_buffer);
12833 }
12834
12835 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12836 }
12837
12838
12839
12840
12841
12842 Lisp_Object
12843 current_message (void)
12844 {
12845 Lisp_Object msg;
12846
12847 if (!BUFFERP (echo_area_buffer[0]))
12848 msg = Qnil;
12849 else
12850 {
12851 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12852 if (NILP (msg))
12853 echo_area_buffer[0] = Qnil;
12854 }
12855
12856 return msg;
12857 }
12858
12859
12860 static bool
12861 current_message_1 (void *a1, Lisp_Object a2)
12862 {
12863 Lisp_Object *msg = a1;
12864
12865 if (Z > BEG)
12866 *msg = make_buffer_string (BEG, Z, true);
12867 else
12868 *msg = Qnil;
12869 return false;
12870 }
12871
12872
12873
12874
12875
12876
12877
12878 bool
12879 push_message (void)
12880 {
12881 Lisp_Object msg = current_message ();
12882 Vmessage_stack = Fcons (msg, Vmessage_stack);
12883 return STRINGP (msg);
12884 }
12885
12886
12887
12888
12889 void
12890 restore_message (void)
12891 {
12892 eassert (CONSP (Vmessage_stack));
12893 message3_nolog (XCAR (Vmessage_stack));
12894 }
12895
12896
12897
12898
12899 void
12900 pop_message_unwind (void)
12901 {
12902
12903 eassert (CONSP (Vmessage_stack));
12904 Vmessage_stack = XCDR (Vmessage_stack);
12905 }
12906
12907
12908
12909
12910
12911
12912 void
12913 check_message_stack (void)
12914 {
12915 if (!NILP (Vmessage_stack))
12916 emacs_abort ();
12917 }
12918
12919 void
12920 clear_message_stack (void)
12921 {
12922 Vmessage_stack = Qnil;
12923 }
12924
12925
12926
12927
12928 void
12929 truncate_echo_area (ptrdiff_t nchars)
12930 {
12931 if (nchars == 0)
12932 echo_area_buffer[0] = Qnil;
12933 else if (!noninteractive
12934 && INTERACTIVE
12935 && !NILP (echo_area_buffer[0]))
12936 {
12937 struct frame *sf = SELECTED_FRAME ();
12938
12939
12940
12941 if (sf->glyphs_initialized_p)
12942 with_echo_area_buffer (0, 0, truncate_message_1,
12943 (void *) (intptr_t) nchars, Qnil);
12944 }
12945 }
12946
12947
12948
12949
12950
12951 static bool
12952 truncate_message_1 (void *a1, Lisp_Object a2)
12953 {
12954 intptr_t nchars = (intptr_t) a1;
12955 if (BEG + nchars < Z)
12956 del_range (BEG + nchars, Z);
12957 if (Z == BEG)
12958 echo_area_buffer[0] = Qnil;
12959 return false;
12960 }
12961
12962 extern intptr_t garbage_collection_inhibited;
12963
12964
12965
12966 static void
12967 set_message (Lisp_Object string)
12968 {
12969 Lisp_Object message = Qnil;
12970
12971 eassert (STRINGP (string));
12972
12973 if (FUNCTIONP (Vset_message_function)
12974
12975
12976
12977 && !garbage_collection_inhibited)
12978 {
12979 specpdl_ref count = SPECPDL_INDEX ();
12980 specbind (Qinhibit_quit, Qt);
12981 message = safe_call1 (Vset_message_function, string);
12982 unbind_to (count, Qnil);
12983
12984 if (STRINGP (message))
12985 {
12986 string = message;
12987 message = Qnil;
12988 }
12989 }
12990
12991 if (NILP (message))
12992 {
12993 message_enable_multibyte = STRING_MULTIBYTE (string);
12994
12995 with_echo_area_buffer (0, -1, set_message_1, 0, string);
12996 message_buf_print = false;
12997 help_echo_showing_p = false;
12998 }
12999
13000 if (STRINGP (Vdebug_on_message)
13001 && STRINGP (string)
13002 && fast_string_match (Vdebug_on_message, string) >= 0)
13003 call_debugger (list2 (Qerror, string));
13004 }
13005
13006
13007
13008
13009
13010
13011 static bool
13012 set_message_1 (void *a1, Lisp_Object string)
13013 {
13014 eassert (STRINGP (string));
13015
13016
13017
13018
13019
13020
13021 if (!message_enable_multibyte
13022 && unibyte_display_via_language_environment
13023 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13024 Fset_buffer_multibyte (Qnil);
13025 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13026 Fset_buffer_multibyte (Qt);
13027
13028 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13029 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13030 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13031
13032
13033 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13034
13035
13036
13037
13038 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13039
13040 return false;
13041 }
13042
13043
13044
13045
13046
13047 void
13048 clear_message (bool current_p, bool last_displayed_p)
13049 {
13050 Lisp_Object preserve = Qnil;
13051
13052 if (current_p)
13053 {
13054 if (FUNCTIONP (Vclear_message_function)
13055
13056 && !garbage_collection_inhibited)
13057 {
13058 specpdl_ref count = SPECPDL_INDEX ();
13059 specbind (Qinhibit_quit, Qt);
13060 preserve = safe_call (1, Vclear_message_function);
13061 unbind_to (count, Qnil);
13062 }
13063
13064 if (!EQ (preserve, Qdont_clear_message))
13065 {
13066 echo_area_buffer[0] = Qnil;
13067 message_cleared_p = true;
13068 }
13069 }
13070
13071 if (last_displayed_p)
13072 echo_area_buffer[1] = Qnil;
13073
13074 message_buf_print = false;
13075 }
13076
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086 static void
13087 clear_garbaged_frames (void)
13088 {
13089 if (frame_garbaged)
13090 {
13091 Lisp_Object tail, frame;
13092 struct frame *sf = SELECTED_FRAME ();
13093
13094 FOR_EACH_FRAME (tail, frame)
13095 {
13096 struct frame *f = XFRAME (frame);
13097
13098 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
13099 {
13100 if (f->resized_p
13101
13102
13103
13104
13105
13106 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13107 redraw_frame (f);
13108 else
13109 clear_current_matrices (f);
13110
13111 #ifdef HAVE_WINDOW_SYSTEM
13112 if (FRAME_WINDOW_P (f)
13113 && FRAME_RIF (f)->clear_under_internal_border)
13114 FRAME_RIF (f)->clear_under_internal_border (f);
13115 #endif
13116 fset_redisplay (f);
13117 f->garbaged = false;
13118 f->resized_p = false;
13119 }
13120 }
13121
13122 frame_garbaged = false;
13123 }
13124 }
13125
13126
13127
13128
13129
13130 static void
13131 echo_area_display (bool update_frame_p)
13132 {
13133 Lisp_Object mini_window;
13134 struct window *w;
13135 struct frame *f;
13136 bool window_height_changed_p = false;
13137 struct frame *sf = SELECTED_FRAME ();
13138
13139 mini_window = FRAME_MINIBUF_WINDOW (sf);
13140 if (NILP (mini_window))
13141 return;
13142
13143 w = XWINDOW (mini_window);
13144 f = XFRAME (WINDOW_FRAME (w));
13145
13146
13147 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
13148 return;
13149
13150 #ifdef HAVE_WINDOW_SYSTEM
13151
13152
13153
13154 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13155 return;
13156 #endif
13157
13158
13159 clear_garbaged_frames ();
13160
13161 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13162 {
13163 echo_area_window = mini_window;
13164 window_height_changed_p = display_echo_area (w);
13165 w->must_be_updated_p = true;
13166
13167
13168
13169
13170
13171 if (update_frame_p && !redisplaying_p)
13172 {
13173 int n = 0;
13174
13175
13176
13177
13178
13179
13180 if (!display_completed)
13181 {
13182 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13183
13184 #ifdef HAVE_WINDOW_SYSTEM
13185 if (FRAME_WINDOW_P (f)
13186 && FRAME_RIF (f)->clear_under_internal_border)
13187 FRAME_RIF (f)->clear_under_internal_border (f);
13188 #endif
13189 }
13190
13191 if (window_height_changed_p
13192
13193
13194 && !NILP (Vrun_hooks))
13195 {
13196
13197
13198
13199 specpdl_ref count = SPECPDL_INDEX ();
13200 specbind (Qredisplay_dont_pause, Qt);
13201 fset_redisplay (f);
13202 redisplay_internal ();
13203 unbind_to (count, Qnil);
13204 }
13205 else if (FRAME_WINDOW_P (f) && n == 0)
13206 {
13207
13208
13209
13210 update_single_window (w);
13211 flush_frame (f);
13212 }
13213 else
13214 update_frame (f, true, true);
13215
13216
13217
13218
13219 if (cursor_in_echo_area)
13220 wset_redisplay (XWINDOW (mini_window));
13221 }
13222 }
13223 else if (!EQ (mini_window, selected_window))
13224 wset_redisplay (XWINDOW (mini_window));
13225
13226
13227 echo_area_buffer[1] = echo_area_buffer[0];
13228
13229 echo_message_buffer = Qnil;
13230
13231
13232
13233
13234 if (EQ (mini_window, selected_window))
13235 CHARPOS (this_line_start_pos) = 0;
13236
13237 if (window_height_changed_p)
13238 {
13239 fset_redisplay (f);
13240
13241
13242
13243
13244
13245 clear_garbaged_frames ();
13246 }
13247 }
13248
13249
13250
13251 static bool
13252 window_buffer_changed (struct window *w)
13253 {
13254 struct buffer *b = XBUFFER (w->contents);
13255
13256 eassert (BUFFER_LIVE_P (b));
13257
13258 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13259 }
13260
13261
13262
13263 static bool
13264 mode_line_update_needed (struct window *w)
13265 {
13266 return (w->column_number_displayed != -1
13267 && !(PT == w->last_point && !window_outdated (w))
13268 && (w->column_number_displayed != current_column ()));
13269 }
13270
13271
13272
13273
13274 static bool
13275 window_frozen_p (struct window *w)
13276 {
13277 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13278 {
13279 Lisp_Object window;
13280
13281 XSETWINDOW (window, w);
13282 if (MINI_WINDOW_P (w))
13283 return false;
13284 else if (EQ (window, selected_window))
13285 return false;
13286 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13287 && EQ (window, Vminibuf_scroll_window))
13288
13289 return false;
13290 else
13291 return true;
13292 }
13293 return false;
13294 }
13295
13296
13297
13298
13299
13300
13301
13302
13303
13304 static char *mode_line_noprop_buf;
13305
13306
13307
13308 static char *mode_line_noprop_buf_end;
13309 static char *mode_line_noprop_ptr;
13310
13311 #define MODE_LINE_NOPROP_LEN(start) \
13312 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13313
13314 static enum {
13315 MODE_LINE_DISPLAY = 0,
13316 MODE_LINE_TITLE,
13317 MODE_LINE_NOPROP,
13318 MODE_LINE_STRING
13319 } mode_line_target;
13320
13321
13322
13323 static Lisp_Object mode_line_proptrans_alist;
13324
13325
13326 static Lisp_Object mode_line_string_list;
13327
13328
13329 static Lisp_Object mode_line_string_face;
13330 static Lisp_Object mode_line_string_face_prop;
13331
13332
13333
13334
13335 static Lisp_Object Vmode_line_unwind_vector;
13336
13337 static Lisp_Object
13338 format_mode_line_unwind_data (struct frame *target_frame,
13339 struct buffer *obuf,
13340 Lisp_Object owin,
13341 bool save_proptrans)
13342 {
13343 Lisp_Object vector, tmp;
13344
13345
13346
13347 vector = Vmode_line_unwind_vector;
13348 Vmode_line_unwind_vector = Qnil;
13349
13350 if (NILP (vector))
13351 vector = make_nil_vector (12);
13352
13353 ASET (vector, 0, make_fixnum (mode_line_target));
13354 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13355 ASET (vector, 2, mode_line_string_list);
13356 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13357 ASET (vector, 4, mode_line_string_face);
13358 ASET (vector, 5, mode_line_string_face_prop);
13359
13360 if (obuf)
13361 XSETBUFFER (tmp, obuf);
13362 else
13363 tmp = Qnil;
13364 ASET (vector, 6, tmp);
13365 ASET (vector, 7, owin);
13366 if (target_frame)
13367 {
13368 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13369 struct buffer *b = XBUFFER (buffer);
13370 struct buffer *cb = current_buffer;
13371
13372
13373
13374
13375 ASET (vector, 8, target_frame->selected_window);
13376 if (FRAME_TERMCAP_P (target_frame))
13377 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13378
13379
13380
13381
13382 ASET (vector, 10, buffer);
13383 current_buffer = b;
13384 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13385 current_buffer = cb;
13386 }
13387
13388 return vector;
13389 }
13390
13391 static void
13392 unwind_format_mode_line (Lisp_Object vector)
13393 {
13394 Lisp_Object old_window = AREF (vector, 7);
13395 Lisp_Object target_frame_window = AREF (vector, 8);
13396 Lisp_Object old_top_frame = AREF (vector, 9);
13397
13398 mode_line_target = XFIXNUM (AREF (vector, 0));
13399 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13400 mode_line_string_list = AREF (vector, 2);
13401 if (! EQ (AREF (vector, 3), Qt))
13402 mode_line_proptrans_alist = AREF (vector, 3);
13403 mode_line_string_face = AREF (vector, 4);
13404 mode_line_string_face_prop = AREF (vector, 5);
13405
13406
13407 if (WINDOW_LIVE_P (old_window))
13408 {
13409
13410
13411
13412 if (WINDOW_LIVE_P (target_frame_window))
13413 {
13414 Lisp_Object frame
13415 = WINDOW_FRAME (XWINDOW (target_frame_window));
13416
13417 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13418 Fselect_window (target_frame_window, Qt);
13419
13420 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13421
13422
13423 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13424 Fselect_frame (old_top_frame, Qt);
13425 }
13426
13427 Fselect_window (old_window, Qt);
13428
13429
13430
13431
13432 if (WINDOW_LIVE_P (target_frame_window))
13433 {
13434 Lisp_Object buffer = AREF (vector, 10);
13435
13436 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13437 {
13438 struct buffer *cb = current_buffer;
13439
13440 current_buffer = XBUFFER (buffer);
13441 set_point_from_marker (AREF (vector, 11));
13442 ASET (vector, 11, Qnil);
13443 current_buffer = cb;
13444 }
13445 }
13446 }
13447
13448 if (!NILP (AREF (vector, 6)))
13449 {
13450 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13451 ASET (vector, 6, Qnil);
13452 }
13453
13454 Vmode_line_unwind_vector = vector;
13455 }
13456
13457
13458
13459
13460
13461 static void
13462 store_mode_line_noprop_char (char c)
13463 {
13464
13465
13466 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13467 {
13468 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13469 ptrdiff_t size = len;
13470 mode_line_noprop_buf =
13471 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13472 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13473 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13474 }
13475
13476 *mode_line_noprop_ptr++ = c;
13477 }
13478
13479
13480
13481
13482
13483
13484
13485
13486
13487
13488 static int
13489 store_mode_line_noprop (const char *string, int field_width, int precision)
13490 {
13491 const unsigned char *str = (const unsigned char *) string;
13492 int n = 0;
13493 ptrdiff_t dummy, nbytes;
13494
13495
13496 nbytes = strlen (string);
13497 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13498 while (nbytes--)
13499 store_mode_line_noprop_char (*str++);
13500
13501
13502 while (field_width > 0
13503 && n < field_width)
13504 {
13505 store_mode_line_noprop_char (' ');
13506 ++n;
13507 }
13508
13509 return n;
13510 }
13511
13512
13513
13514
13515
13516 #ifdef HAVE_WINDOW_SYSTEM
13517
13518
13519
13520
13521
13522 void
13523 gui_consider_frame_title (Lisp_Object frame)
13524 {
13525 struct frame *f = XFRAME (frame);
13526 Lisp_Object format_data;
13527
13528 if ((FRAME_WINDOW_P (f)
13529 || FRAME_MINIBUF_ONLY_P (f)
13530 || f->explicit_name)
13531 && !FRAME_TOOLTIP_P (f))
13532 {
13533
13534 Lisp_Object tail, other_frame, fmt;
13535 ptrdiff_t title_start;
13536 char *title;
13537 ptrdiff_t len;
13538 struct it it;
13539 specpdl_ref count = SPECPDL_INDEX ();
13540
13541 FOR_EACH_FRAME (tail, other_frame)
13542 {
13543 struct frame *tf = XFRAME (other_frame);
13544
13545 if (tf != f
13546 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13547 && !FRAME_MINIBUF_ONLY_P (tf)
13548 && !FRAME_PARENT_FRAME (tf)
13549 && !FRAME_TOOLTIP_P (tf)
13550 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13551 break;
13552 }
13553
13554
13555 multiple_frames = CONSP (tail);
13556
13557
13558
13559
13560
13561
13562
13563
13564
13565
13566
13567
13568 specbind (Qinhibit_redisplay, Qt);
13569
13570
13571
13572
13573
13574
13575
13576
13577 format_data = format_mode_line_unwind_data (f, current_buffer,
13578 selected_window,
13579 false);
13580 record_unwind_protect (unwind_format_mode_line, format_data);
13581
13582 Fselect_window (f->selected_window, Qt);
13583 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13584 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13585 ? Vicon_title_format : Vframe_title_format);
13586
13587 mode_line_target = MODE_LINE_TITLE;
13588 title_start = MODE_LINE_NOPROP_LEN (0);
13589 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13590 NULL, DEFAULT_FACE_ID);
13591 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13592 len = MODE_LINE_NOPROP_LEN (title_start);
13593 title = mode_line_noprop_buf + title_start;
13594
13595
13596 ptrdiff_t nchars = 0;
13597 len = str_as_multibyte ((unsigned char *) title,
13598 mode_line_noprop_buf_end - title,
13599 len, &nchars);
13600 unbind_to (count, Qnil);
13601
13602
13603
13604
13605
13606
13607 if ((! STRINGP (f->name)
13608 || SBYTES (f->name) != len
13609 || memcmp (title, SDATA (f->name), len) != 0)
13610 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13611 {
13612 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13613 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13614 }
13615 }
13616 }
13617
13618 #endif
13619
13620
13621
13622
13623
13624
13625
13626 #define REDISPLAY_SOME_P() \
13627 ((windows_or_buffers_changed == 0 \
13628 || windows_or_buffers_changed == REDISPLAY_SOME) \
13629 && (update_mode_lines == 0 \
13630 || update_mode_lines == REDISPLAY_SOME))
13631
13632 static bool
13633 needs_no_redisplay (struct window *w)
13634 {
13635 struct buffer *buffer = XBUFFER (w->contents);
13636 struct frame *f = XFRAME (w->frame);
13637 return (REDISPLAY_SOME_P ()
13638 && !w->redisplay
13639 && !w->update_mode_line
13640 && !f->face_change
13641 && !f->redisplay
13642 && !buffer->text->redisplay
13643 && window_point (w) == w->last_point);
13644 }
13645
13646
13647
13648
13649 static void
13650 prepare_menu_bars (void)
13651 {
13652 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13653 bool some_windows = REDISPLAY_SOME_P ();
13654
13655 if (FUNCTIONP (Vpre_redisplay_function))
13656 {
13657 Lisp_Object windows = all_windows ? Qt : Qnil;
13658 if (all_windows && some_windows)
13659 {
13660 Lisp_Object ws = window_list ();
13661 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13662 {
13663 Lisp_Object this = XCAR (ws);
13664 struct window *w = XWINDOW (this);
13665
13666
13667 if (!needs_no_redisplay (w))
13668 windows = Fcons (this, windows);
13669 }
13670 }
13671 safe__call1 (true, Vpre_redisplay_function, windows);
13672 }
13673
13674
13675
13676
13677 #ifdef HAVE_WINDOW_SYSTEM
13678 if (all_windows)
13679 {
13680 Lisp_Object tail, frame;
13681
13682 FOR_EACH_FRAME (tail, frame)
13683 {
13684 struct frame *f = XFRAME (frame);
13685 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13686 if (some_windows
13687 && !f->redisplay
13688 && !w->redisplay
13689 && !XBUFFER (w->contents)->text->redisplay)
13690 continue;
13691
13692 if (!FRAME_TOOLTIP_P (f)
13693 && (FRAME_ICONIFIED_P (f)
13694 || FRAME_VISIBLE_P (f) == 1
13695
13696
13697
13698
13699
13700
13701
13702
13703
13704 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13705 gui_consider_frame_title (frame);
13706 }
13707 }
13708 #endif
13709
13710
13711
13712
13713 if (all_windows)
13714 {
13715 Lisp_Object tail, frame;
13716 specpdl_ref count = SPECPDL_INDEX ();
13717
13718
13719 bool menu_bar_hooks_run = false;
13720
13721 record_unwind_save_match_data ();
13722
13723 FOR_EACH_FRAME (tail, frame)
13724 {
13725 struct frame *f = XFRAME (frame);
13726 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13727
13728
13729 if (FRAME_TOOLTIP_P (f))
13730 continue;
13731
13732 if (some_windows
13733 && !f->redisplay
13734 && !w->redisplay
13735 && !XBUFFER (w->contents)->text->redisplay)
13736 continue;
13737
13738 if (!FRAME_PARENT_FRAME (f))
13739 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13740
13741 update_tab_bar (f, false);
13742 #ifdef HAVE_WINDOW_SYSTEM
13743 update_tool_bar (f, false);
13744 #endif
13745 }
13746
13747 unbind_to (count, Qnil);
13748 }
13749 else
13750 {
13751 struct frame *sf = SELECTED_FRAME ();
13752
13753 if (!FRAME_PARENT_FRAME (sf))
13754 update_menu_bar (sf, true, false);
13755
13756 update_tab_bar (sf, true);
13757 #ifdef HAVE_WINDOW_SYSTEM
13758 update_tool_bar (sf, true);
13759 #endif
13760 }
13761 }
13762
13763
13764
13765
13766
13767
13768
13769
13770
13771
13772
13773
13774
13775 static bool
13776 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13777 {
13778 Lisp_Object window;
13779 struct window *w;
13780
13781
13782
13783
13784 if (inhibit_menubar_update)
13785 return hooks_run;
13786
13787 window = FRAME_SELECTED_WINDOW (f);
13788 w = XWINDOW (window);
13789
13790 if (FRAME_WINDOW_P (f)
13791 ?
13792 #ifdef HAVE_EXT_MENU_BAR
13793 FRAME_EXTERNAL_MENU_BAR (f)
13794 #else
13795 FRAME_MENU_BAR_LINES (f) > 0
13796 #endif
13797 : FRAME_MENU_BAR_LINES (f) > 0)
13798 {
13799
13800
13801
13802
13803
13804
13805
13806 if (windows_or_buffers_changed
13807
13808
13809 || update_mode_lines
13810 || window_buffer_changed (w))
13811 {
13812 struct buffer *prev = current_buffer;
13813 specpdl_ref count = SPECPDL_INDEX ();
13814
13815 specbind (Qinhibit_menubar_update, Qt);
13816
13817 set_buffer_internal_1 (XBUFFER (w->contents));
13818 if (save_match_data)
13819 record_unwind_save_match_data ();
13820 if (NILP (Voverriding_local_map_menu_flag))
13821 {
13822 specbind (Qoverriding_terminal_local_map, Qnil);
13823 specbind (Qoverriding_local_map, Qnil);
13824 }
13825
13826 if (!hooks_run)
13827 {
13828
13829 safe_run_hooks (Qactivate_menubar_hook);
13830
13831
13832
13833 safe_run_hooks (Qmenu_bar_update_hook);
13834
13835 hooks_run = true;
13836 }
13837
13838 XSETFRAME (Vmenu_updating_frame, f);
13839 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13840
13841
13842 #ifdef HAVE_EXT_MENU_BAR
13843 if (FRAME_WINDOW_P (f))
13844 {
13845 #if defined (HAVE_NS)
13846
13847
13848 if (f == SELECTED_FRAME ())
13849 #endif
13850 set_frame_menubar (f, false);
13851 }
13852 else
13853
13854
13855 w->update_mode_line = true;
13856 #else
13857
13858
13859 w->update_mode_line = true;
13860 #endif
13861
13862 unbind_to (count, Qnil);
13863 set_buffer_internal_1 (prev);
13864 }
13865 }
13866
13867 return hooks_run;
13868 }
13869
13870
13871
13872
13873
13874
13875
13876
13877
13878
13879
13880
13881 static void
13882 restore_selected_window (Lisp_Object window)
13883 {
13884 if (WINDOW_LIVE_P (window))
13885
13886
13887 {
13888 selected_window = window;
13889 selected_frame = XWINDOW (window)->frame;
13890 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13891 }
13892 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13893
13894
13895 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13896 else
13897
13898
13899
13900 {
13901 Lisp_Object tail;
13902 Lisp_Object frame UNINIT;
13903
13904 FOR_EACH_FRAME (tail, frame)
13905 {
13906 struct frame *f = XFRAME (frame);
13907
13908 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13909 {
13910 selected_frame = frame;
13911 selected_window = FRAME_SELECTED_WINDOW (f);
13912
13913 return;
13914 }
13915 }
13916
13917
13918 emacs_abort ();
13919 }
13920 }
13921
13922
13923 static void
13924 restore_frame_selected_window (Lisp_Object window)
13925 {
13926 if (WINDOW_LIVE_P (window))
13927
13928
13929
13930 {
13931 Lisp_Object frame = XWINDOW (window)->frame;
13932
13933 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13934 if (EQ (frame, selected_frame))
13935 selected_window = window;
13936 }
13937 }
13938
13939
13940
13941
13942
13943
13944 static void
13945 update_tab_bar (struct frame *f, bool save_match_data)
13946 {
13947 bool do_update = false;
13948
13949 #ifdef HAVE_WINDOW_SYSTEM
13950 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13951 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13952 do_update = true;
13953 }
13954 else
13955 #endif
13956 if (FRAME_TAB_BAR_LINES (f) > 0)
13957 do_update = true;
13958
13959 if (do_update)
13960 {
13961 Lisp_Object window;
13962 struct window *w;
13963
13964 window = FRAME_SELECTED_WINDOW (f);
13965 w = XWINDOW (window);
13966
13967
13968
13969
13970
13971
13972
13973
13974 if (windows_or_buffers_changed
13975 || w->update_mode_line
13976 || update_mode_lines
13977 || window_buffer_changed (w))
13978 {
13979 struct buffer *prev = current_buffer;
13980 specpdl_ref count = SPECPDL_INDEX ();
13981 Lisp_Object new_tab_bar;
13982 int new_n_tab_bar;
13983
13984
13985
13986
13987 set_buffer_internal_1 (XBUFFER (w->contents));
13988
13989
13990 if (save_match_data)
13991 record_unwind_save_match_data ();
13992
13993
13994 if (NILP (Voverriding_local_map_menu_flag))
13995 {
13996 specbind (Qoverriding_terminal_local_map, Qnil);
13997 specbind (Qoverriding_local_map, Qnil);
13998 }
13999
14000
14001
14002
14003
14004 eassert (EQ (selected_window,
14005
14006
14007 XFRAME (selected_frame)->selected_window));
14008 #ifdef HAVE_WINDOW_SYSTEM
14009 Lisp_Object frame;
14010 record_unwind_protect (restore_selected_window, selected_window);
14011 XSETFRAME (frame, f);
14012 selected_frame = frame;
14013 selected_window = FRAME_SELECTED_WINDOW (f);
14014 #endif
14015
14016
14017 new_tab_bar
14018 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14019 &new_n_tab_bar);
14020
14021
14022 if (new_n_tab_bar != f->n_tab_bar_items
14023 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14024 {
14025
14026
14027
14028 block_input ();
14029 fset_tab_bar_items (f, new_tab_bar);
14030 f->n_tab_bar_items = new_n_tab_bar;
14031 w->update_mode_line = true;
14032 unblock_input ();
14033 }
14034
14035 unbind_to (count, Qnil);
14036 set_buffer_internal_1 (prev);
14037 }
14038 }
14039 }
14040
14041
14042
14043
14044
14045
14046
14047
14048
14049
14050
14051 static void
14052 display_tab_bar (struct window *w)
14053 {
14054 struct frame *f = XFRAME (WINDOW_FRAME (w));
14055 struct it it;
14056 Lisp_Object items;
14057 int i;
14058
14059
14060 #ifdef HAVE_NTGUI
14061 if (FRAME_W32_P (f))
14062 return;
14063 #endif
14064 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14065 if (FRAME_X_P (f))
14066 return;
14067 #endif
14068
14069 #ifdef HAVE_NS
14070 if (FRAME_NS_P (f))
14071 return;
14072 #endif
14073
14074 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14075 eassert (!FRAME_WINDOW_P (f));
14076 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14077 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14078 TAB_BAR_FACE_ID);
14079 it.first_visible_x = 0;
14080 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14081 #elif defined (HAVE_X_WINDOWS)
14082 if (FRAME_WINDOW_P (f))
14083 {
14084
14085
14086 struct window *tab_w;
14087 tab_w = XWINDOW (f->tab_bar_window);
14088 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14089 TAB_BAR_FACE_ID);
14090 it.first_visible_x = 0;
14091 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14092 }
14093 else
14094 #endif
14095 {
14096
14097
14098 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14099 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14100 TAB_BAR_FACE_ID);
14101 it.first_visible_x = 0;
14102 it.last_visible_x = FRAME_COLS (f);
14103 }
14104
14105
14106
14107
14108 it.paragraph_embedding = L2R;
14109
14110
14111 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14112 {
14113 struct glyph_row *row = it.glyph_row + i;
14114 clear_glyph_row (row);
14115 row->enabled_p = true;
14116 row->full_width_p = true;
14117 row->reversed_p = false;
14118 }
14119
14120
14121 items = it.f->tab_bar_items;
14122 int j;
14123 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14124 {
14125 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14126
14127
14128 if (NILP (string))
14129 break;
14130
14131 if (it.current_x < it.last_visible_x)
14132 display_string (NULL, string, Qnil, 0, 0, &it,
14133 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14134 }
14135
14136
14137 if (it.current_x < it.last_visible_x)
14138 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14139
14140
14141 compute_line_metrics (&it);
14142 }
14143
14144 #ifdef HAVE_WINDOW_SYSTEM
14145
14146
14147
14148
14149
14150 static void
14151 build_desired_tab_bar_string (struct frame *f)
14152 {
14153 int i;
14154 Lisp_Object caption;
14155
14156 caption = Qnil;
14157
14158
14159 fset_desired_tab_bar_string (f, build_string (""));
14160
14161
14162
14163
14164 for (i = 0; i < f->n_tab_bar_items; ++i)
14165 {
14166 #define PROP(IDX) \
14167 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14168
14169 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14170
14171
14172
14173
14174
14175 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14176
14177 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14178 props, caption);
14179
14180 f->desired_tab_bar_string =
14181 concat2 (f->desired_tab_bar_string, caption);
14182
14183 #undef PROP
14184 }
14185 }
14186
14187
14188
14189
14190
14191
14192
14193
14194
14195
14196
14197
14198
14199
14200 static void
14201 display_tab_bar_line (struct it *it, int height)
14202 {
14203 struct glyph_row *row = it->glyph_row;
14204 int max_x = it->last_visible_x;
14205 struct glyph *last;
14206
14207
14208 clear_glyph_row (row);
14209 row->enabled_p = true;
14210 row->y = it->current_y;
14211
14212
14213
14214 it->start_of_box_run_p = true;
14215
14216 bool enough = false;
14217 while (it->current_x < max_x)
14218 {
14219 int x, n_glyphs_before, i, nglyphs;
14220 struct it it_before;
14221
14222
14223 if (!get_next_display_element (it))
14224 {
14225
14226 if (height < 0 && !it->hpos)
14227 return;
14228 break;
14229 }
14230
14231
14232 n_glyphs_before = row->used[TEXT_AREA];
14233 it_before = *it;
14234
14235 PRODUCE_GLYPHS (it);
14236
14237 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14238 i = 0;
14239 x = it_before.current_x;
14240 while (i < nglyphs)
14241 {
14242 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14243
14244 if (x + glyph->pixel_width > max_x)
14245 {
14246
14247 row->used[TEXT_AREA] = n_glyphs_before;
14248 *it = it_before;
14249
14250
14251
14252 if (n_glyphs_before == 0
14253 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14254 break;
14255 goto out;
14256 }
14257
14258 ++it->hpos;
14259 x += glyph->pixel_width;
14260 ++i;
14261 }
14262
14263 enough = ITERATOR_AT_END_OF_LINE_P (it);
14264 set_iterator_to_next (it, true);
14265
14266
14267 if (enough)
14268 break;
14269 }
14270
14271 out:;
14272
14273 row->displays_text_p = row->used[TEXT_AREA] != 0;
14274
14275
14276
14277
14278
14279
14280
14281 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14282 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14283 it->face_id = DEFAULT_FACE_ID;
14284
14285 extend_face_to_end_of_line (it);
14286 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14287 last->right_box_line_p = true;
14288 if (last == row->glyphs[TEXT_AREA])
14289 last->left_box_line_p = true;
14290
14291
14292 if ((height -= it->max_ascent + it->max_descent) > 0)
14293 {
14294
14295 height %= FRAME_LINE_HEIGHT (it->f);
14296 it->max_ascent += height / 2;
14297 it->max_descent += (height + 1) / 2;
14298 }
14299
14300 compute_line_metrics (it);
14301
14302
14303 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14304 {
14305 row->height = row->phys_height = it->last_visible_y - row->y;
14306 row->visible_height = row->height;
14307 row->ascent = row->phys_ascent = 0;
14308 row->extra_line_spacing = 0;
14309 }
14310
14311 row->full_width_p = true;
14312 row->continued_p = false;
14313 row->truncated_on_left_p = false;
14314 row->truncated_on_right_p = false;
14315
14316 it->current_x = it->hpos = 0;
14317 it->current_y += row->height;
14318 ++it->vpos;
14319 ++it->glyph_row;
14320 }
14321
14322
14323
14324
14325
14326 static int
14327 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14328 {
14329 struct window *w = XWINDOW (f->tab_bar_window);
14330 struct it it;
14331
14332
14333
14334 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14335
14336
14337
14338 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14339 temp_row->reversed_p = false;
14340 it.first_visible_x = 0;
14341 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14342 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14343 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14344 it.paragraph_embedding = L2R;
14345
14346 clear_glyph_row (temp_row);
14347 while (!ITERATOR_AT_END_P (&it))
14348 {
14349 it.glyph_row = temp_row;
14350 display_tab_bar_line (&it, -1);
14351 }
14352 clear_glyph_row (temp_row);
14353
14354
14355 if (n_rows)
14356 *n_rows = it.vpos > 0 ? it.vpos : -1;
14357
14358 if (pixelwise)
14359 return it.current_y;
14360 else
14361 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14362 }
14363
14364 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14365 0, 2, 0,
14366 doc:
14367
14368 )
14369 (Lisp_Object frame, Lisp_Object pixelwise)
14370 {
14371 int height = 0;
14372
14373 struct frame *f = decode_any_frame (frame);
14374
14375 if (WINDOWP (f->tab_bar_window)
14376 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14377 {
14378 update_tab_bar (f, true);
14379 if (f->n_tab_bar_items)
14380 {
14381 build_desired_tab_bar_string (f);
14382 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14383 }
14384 }
14385
14386 return make_fixnum (height);
14387 }
14388
14389
14390
14391
14392 static bool
14393 redisplay_tab_bar (struct frame *f)
14394 {
14395 struct window *w;
14396 struct it it;
14397 struct glyph_row *row;
14398
14399 f->tab_bar_redisplayed = true;
14400
14401
14402
14403
14404
14405 if (!WINDOWP (f->tab_bar_window)
14406 || (w = XWINDOW (f->tab_bar_window),
14407 WINDOW_TOTAL_LINES (w) == 0))
14408 {
14409
14410
14411
14412
14413
14414 f->tab_bar_resized = true;
14415
14416 return false;
14417 }
14418
14419
14420 build_desired_tab_bar_string (f);
14421
14422 int new_nrows;
14423 int new_height = tab_bar_height (f, &new_nrows, true);
14424
14425 if (f->n_tab_bar_rows == 0)
14426 {
14427 f->n_tab_bar_rows = new_nrows;
14428 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14429 frame_default_tab_bar_height = new_height;
14430 }
14431
14432
14433
14434 if (new_nrows > f->n_tab_bar_rows
14435 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14436 && !f->minimize_tab_bar_window_p
14437 && new_height > WINDOW_PIXEL_HEIGHT (w))
14438 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14439 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14440 {
14441 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14442 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14443 if (new_nrows != f->n_tab_bar_rows)
14444 f->n_tab_bar_rows = new_nrows;
14445 clear_glyph_matrix (w->desired_matrix);
14446 f->fonts_changed = true;
14447 return true;
14448 }
14449
14450
14451 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14452 it.first_visible_x = 0;
14453 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14454 row = it.glyph_row;
14455 row->reversed_p = false;
14456 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14457 STRING_MULTIBYTE (f->desired_tab_bar_string));
14458
14459
14460
14461
14462
14463
14464
14465 it.paragraph_embedding = L2R;
14466
14467
14468
14469 if (f->n_tab_bar_rows > 0)
14470 {
14471 int border, rows, height, extra;
14472
14473 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14474 border = XFIXNUM (Vtab_bar_border);
14475 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14476 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14477 else if (EQ (Vtab_bar_border, Qborder_width))
14478 border = f->border_width;
14479 else
14480 border = 0;
14481 if (border < 0)
14482 border = 0;
14483
14484 rows = f->n_tab_bar_rows;
14485 height = max (1, (it.last_visible_y - border) / rows);
14486 extra = it.last_visible_y - border - height * rows;
14487
14488 while (it.current_y < it.last_visible_y)
14489 {
14490 int h = 0;
14491 if (extra > 0 && rows-- > 0)
14492 {
14493 h = (extra + rows - 1) / rows;
14494 extra -= h;
14495 }
14496 display_tab_bar_line (&it, height + h);
14497 }
14498 }
14499 else
14500 {
14501 while (it.current_y < it.last_visible_y)
14502 display_tab_bar_line (&it, 0);
14503 }
14504
14505
14506
14507 w->desired_matrix->no_scrolling_p = true;
14508 w->must_be_updated_p = true;
14509
14510 if (!NILP (Vauto_resize_tab_bars))
14511 {
14512 bool change_height_p = false;
14513
14514
14515
14516 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14517 change_height_p = true;
14518
14519
14520
14521
14522
14523 row = it.glyph_row - 1;
14524
14525
14526
14527
14528 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14529 && row->height >= FRAME_LINE_HEIGHT (f))
14530 change_height_p = true;
14531
14532
14533
14534 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14535 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14536 change_height_p = true;
14537
14538
14539
14540 if (change_height_p)
14541 {
14542 int nrows;
14543 int new_height = tab_bar_height (f, &nrows, true);
14544
14545 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14546 && !f->minimize_tab_bar_window_p)
14547 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14548 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14549 f->minimize_tab_bar_window_p = false;
14550
14551 if (change_height_p)
14552 {
14553 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14554 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14555 frame_default_tab_bar_height = new_height;
14556 clear_glyph_matrix (w->desired_matrix);
14557 f->n_tab_bar_rows = nrows;
14558 f->fonts_changed = true;
14559
14560 return true;
14561 }
14562 }
14563 }
14564
14565 f->minimize_tab_bar_window_p = false;
14566 return false;
14567 }
14568
14569
14570
14571
14572
14573
14574
14575 static bool
14576 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14577 int *prop_idx, bool *close_p)
14578 {
14579 Lisp_Object prop;
14580 ptrdiff_t charpos;
14581
14582
14583
14584
14585 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14586 charpos = max (0, charpos);
14587
14588
14589
14590
14591 prop = Fget_text_property (make_fixnum (charpos),
14592 Qmenu_item, f->current_tab_bar_string);
14593 if (! FIXNUMP (prop))
14594 return false;
14595
14596 *prop_idx = XFIXNUM (prop);
14597
14598 if (close_p)
14599 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14600 Qclose_tab,
14601 f->current_tab_bar_string));
14602
14603 return true;
14604 }
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619
14620
14621
14622
14623
14624
14625
14626 static int
14627 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14628 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14629 {
14630 struct window *w = XWINDOW (f->tab_bar_window);
14631 int area;
14632
14633
14634 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14635 if (*glyph == NULL)
14636 return -1;
14637
14638
14639
14640 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14641 return -1;
14642
14643 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14644 }
14645
14646
14647
14648
14649
14650
14651
14652 int
14653 get_tab_bar_item_kbd (struct frame *f, int x, int y, int *prop_idx,
14654 bool *close_p)
14655 {
14656 struct window *w;
14657 int area, vpos, hpos;
14658 struct glyph *glyph;
14659
14660 w = XWINDOW (f->tab_bar_window);
14661
14662
14663 frame_to_window_pixel_xy (w, &x, &y);
14664
14665
14666 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, 0,
14667 0, &area);
14668 if (glyph == NULL)
14669 return -1;
14670
14671
14672
14673 if (!tab_bar_item_info (f, glyph, prop_idx, close_p))
14674 return -1;
14675
14676 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14677 }
14678
14679
14680
14681
14682
14683
14684
14685 Lisp_Object
14686 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14687 int modifiers)
14688 {
14689 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14690 struct window *w = XWINDOW (f->tab_bar_window);
14691 int hpos, vpos, prop_idx;
14692 bool close_p;
14693 struct glyph *glyph;
14694 Lisp_Object enabled_p;
14695 int ts;
14696
14697 frame_to_window_pixel_xy (w, &x, &y);
14698 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14699 if (ts == -1)
14700 return Fcons (Qtab_bar, Qnil);
14701
14702
14703 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14704 if (NILP (enabled_p))
14705 return Qnil;
14706
14707 if (down_p)
14708 {
14709
14710 if (!NILP (Vmouse_highlight))
14711 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14712 f->last_tab_bar_item = prop_idx;
14713 }
14714 else
14715 {
14716
14717 if (!NILP (Vmouse_highlight))
14718 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14719 f->last_tab_bar_item = -1;
14720 }
14721
14722 Lisp_Object caption =
14723 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14724
14725 AUTO_LIST2 (props, Qmenu_item,
14726 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14727 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14728 close_p ? Qt : Qnil));
14729
14730 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14731 props, caption);
14732
14733 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14734 }
14735
14736
14737
14738
14739
14740
14741 static void
14742 note_tab_bar_highlight (struct frame *f, int x, int y)
14743 {
14744 Lisp_Object window = f->tab_bar_window;
14745 struct window *w = XWINDOW (window);
14746 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14747 int hpos, vpos;
14748 struct glyph *glyph;
14749 struct glyph_row *row;
14750 int i;
14751 Lisp_Object enabled_p;
14752 int prop_idx;
14753 bool close_p;
14754 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14755 int rc;
14756
14757
14758
14759 if (x <= 0 || y <= 0)
14760 {
14761 clear_mouse_face (hlinfo);
14762 return;
14763 }
14764
14765 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14766 if (rc < 0)
14767 {
14768
14769 clear_mouse_face (hlinfo);
14770 return;
14771 }
14772 else if (rc == 0)
14773
14774 goto set_help_echo;
14775
14776 clear_mouse_face (hlinfo);
14777
14778 bool mouse_down_p = false;
14779
14780
14781
14782
14783
14784 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14785 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14786 && f == dpyinfo->last_mouse_frame);
14787
14788 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14789 && f->last_tab_bar_item != -1)
14790 return;
14791 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14792
14793
14794 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14795 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14796 {
14797
14798
14799 row = MATRIX_ROW (w->current_matrix, vpos);
14800 for (i = x = 0; i < hpos; ++i)
14801 x += row->glyphs[TEXT_AREA][i].pixel_width;
14802
14803
14804 hlinfo->mouse_face_beg_col = hpos;
14805 hlinfo->mouse_face_beg_row = vpos;
14806 hlinfo->mouse_face_beg_x = x;
14807 hlinfo->mouse_face_past_end = false;
14808
14809 hlinfo->mouse_face_end_col = hpos + 1;
14810 hlinfo->mouse_face_end_row = vpos;
14811 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14812 hlinfo->mouse_face_window = window;
14813 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14814
14815
14816 show_mouse_face (hlinfo, draw);
14817 }
14818
14819 set_help_echo:
14820
14821
14822
14823 help_echo_object = help_echo_window = Qnil;
14824 help_echo_pos = -1;
14825 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14826 if (NILP (help_echo_string))
14827 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14828 }
14829
14830 #endif
14831
14832
14833 static Lisp_Object
14834 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14835 {
14836 ptrdiff_t clen = 0;
14837
14838 for (int i = 0; i < f->n_tab_bar_items; i++)
14839 {
14840 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14841 + TAB_BAR_ITEM_CAPTION));
14842 if (NILP (caption))
14843 return Qnil;
14844 clen += SCHARS (caption);
14845 if (x < clen)
14846 {
14847 *prop_idx = i;
14848 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14849 - (clen - x)),
14850 Qclose_tab,
14851 caption));
14852 return caption;
14853 }
14854 }
14855 return Qnil;
14856 }
14857
14858
14859
14860
14861
14862
14863 Lisp_Object
14864 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14865 struct input_event *event)
14866 {
14867
14868 if (y < FRAME_MENU_BAR_LINES (f)
14869 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14870 return Qnil;
14871
14872
14873 int prop_idx;
14874 bool close_p;
14875 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14876
14877 if (NILP (caption))
14878 return Qnil;
14879
14880 if (NILP (AREF (f->tab_bar_items,
14881 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14882 return Qnil;
14883
14884 if (down_p)
14885 f->last_tab_bar_item = prop_idx;
14886 else
14887 f->last_tab_bar_item = -1;
14888
14889 caption = Fcopy_sequence (caption);
14890
14891 AUTO_LIST2 (props, Qmenu_item,
14892 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14893 + TAB_BAR_ITEM_KEY),
14894 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14895 + TAB_BAR_ITEM_BINDING),
14896 close_p ? Qt : Qnil));
14897
14898 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14899 props, caption);
14900
14901 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14902 }
14903
14904
14905
14906
14907
14908
14909
14910 #ifdef HAVE_WINDOW_SYSTEM
14911
14912
14913
14914
14915
14916
14917 static void
14918 update_tool_bar (struct frame *f, bool save_match_data)
14919 {
14920 #ifdef HAVE_EXT_TOOL_BAR
14921 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14922 #else
14923 bool do_update = (WINDOWP (f->tool_bar_window)
14924 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14925 #endif
14926
14927 if (do_update)
14928 {
14929 Lisp_Object window;
14930 struct window *w;
14931
14932 window = FRAME_SELECTED_WINDOW (f);
14933 w = XWINDOW (window);
14934
14935
14936
14937
14938
14939
14940
14941
14942 if (windows_or_buffers_changed
14943 || w->update_mode_line
14944 || update_mode_lines
14945 || window_buffer_changed (w))
14946 {
14947 struct buffer *prev = current_buffer;
14948 specpdl_ref count = SPECPDL_INDEX ();
14949 Lisp_Object frame, new_tool_bar;
14950 int new_n_tool_bar;
14951
14952
14953
14954
14955 set_buffer_internal_1 (XBUFFER (w->contents));
14956
14957
14958 if (save_match_data)
14959 record_unwind_save_match_data ();
14960
14961
14962 if (NILP (Voverriding_local_map_menu_flag))
14963 {
14964 specbind (Qoverriding_terminal_local_map, Qnil);
14965 specbind (Qoverriding_local_map, Qnil);
14966 }
14967
14968
14969
14970
14971
14972 eassert (EQ (selected_window,
14973
14974
14975 XFRAME (selected_frame)->selected_window));
14976 record_unwind_protect (restore_selected_window, selected_window);
14977 XSETFRAME (frame, f);
14978 selected_frame = frame;
14979 selected_window = FRAME_SELECTED_WINDOW (f);
14980
14981
14982 new_tool_bar
14983 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
14984 &new_n_tool_bar);
14985
14986
14987 if (new_n_tool_bar != f->n_tool_bar_items
14988 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
14989 {
14990
14991
14992
14993 block_input ();
14994 fset_tool_bar_items (f, new_tool_bar);
14995 f->n_tool_bar_items = new_n_tool_bar;
14996 w->update_mode_line = true;
14997 unblock_input ();
14998 }
14999
15000 unbind_to (count, Qnil);
15001 set_buffer_internal_1 (prev);
15002 }
15003 }
15004 }
15005
15006 #ifndef HAVE_EXT_TOOL_BAR
15007
15008
15009
15010
15011
15012
15013
15014
15015 static void
15016 build_desired_tool_bar_string (struct frame *f)
15017 {
15018 int i, size, size_needed;
15019 Lisp_Object image, plist;
15020
15021 image = plist = Qnil;
15022
15023
15024
15025
15026
15027 size = (STRINGP (f->desired_tool_bar_string)
15028 ? SCHARS (f->desired_tool_bar_string)
15029 : 0);
15030
15031
15032 size_needed = f->n_tool_bar_items;
15033
15034
15035
15036 if (size < size_needed || NILP (f->desired_tool_bar_string))
15037
15038
15039 fset_desired_tool_bar_string (f, make_uninit_string (size_needed));
15040 else
15041 {
15042 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
15043 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
15044 props, f->desired_tool_bar_string);
15045 }
15046
15047 f->tool_bar_wraps_p = false;
15048
15049
15050
15051
15052 for (i = 0; i < f->n_tool_bar_items; ++i)
15053 {
15054 #define PROP(IDX) \
15055 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
15056
15057 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15058 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15059 int hmargin, vmargin, relief, idx, end;
15060
15061 if (!NILP (PROP (TOOL_BAR_ITEM_WRAP)))
15062 {
15063
15064
15065 SSET (f->desired_tool_bar_string, i, '\n');
15066
15067
15068
15069 f->tool_bar_wraps_p = true;
15070 continue;
15071 }
15072
15073
15074 SSET (f->desired_tool_bar_string, i, ' ');
15075
15076
15077
15078 image = PROP (TOOL_BAR_ITEM_IMAGES);
15079 if (VECTORP (image))
15080 {
15081 if (enabled_p)
15082 idx = (selected_p
15083 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15084 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15085 else
15086 idx = (selected_p
15087 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15088 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15089
15090 eassert (ASIZE (image) >= idx);
15091 image = AREF (image, idx);
15092 }
15093 else
15094 idx = -1;
15095
15096
15097 if (!valid_image_p (image))
15098 continue;
15099
15100
15101 plist = Fcopy_sequence (XCDR (image));
15102
15103
15104 relief = (tool_bar_button_relief >= 0
15105 ? min (tool_bar_button_relief,
15106 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15107 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15108 hmargin = vmargin = relief;
15109
15110 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15111 INT_MAX - max (hmargin, vmargin)))
15112 {
15113 hmargin += XFIXNAT (Vtool_bar_button_margin);
15114 vmargin += XFIXNAT (Vtool_bar_button_margin);
15115 }
15116 else if (CONSP (Vtool_bar_button_margin))
15117 {
15118 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15119 INT_MAX - hmargin))
15120 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15121
15122 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15123 INT_MAX - vmargin))
15124 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15125 }
15126
15127 if (auto_raise_tool_bar_buttons_p)
15128 {
15129
15130
15131 if (selected_p)
15132 {
15133 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15134 hmargin -= relief;
15135 vmargin -= relief;
15136 }
15137 }
15138 else
15139 {
15140
15141
15142
15143 plist = plist_put (plist, QCrelief,
15144 (selected_p
15145 ? make_fixnum (-relief)
15146 : make_fixnum (relief)));
15147 hmargin -= relief;
15148 vmargin -= relief;
15149 }
15150
15151
15152 if (hmargin || vmargin)
15153 {
15154 if (hmargin == vmargin)
15155 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15156 else
15157 plist = plist_put (plist, QCmargin,
15158 Fcons (make_fixnum (hmargin),
15159 make_fixnum (vmargin)));
15160 }
15161
15162
15163
15164
15165 if (!enabled_p && idx < 0)
15166 plist = plist_put (plist, QCconversion, Qdisabled);
15167
15168
15169
15170
15171
15172 image = Fcons (Qimage, plist);
15173 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15174 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15175
15176
15177
15178
15179 if (i + 1 == f->n_tool_bar_items)
15180 end = SCHARS (f->desired_tool_bar_string);
15181 else
15182 end = i + 1;
15183 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15184 props, f->desired_tool_bar_string);
15185 #undef PROP
15186 }
15187
15188
15189
15190
15191
15192
15193
15194 for (; i < size; ++i)
15195
15196 SSET (f->desired_tool_bar_string, i, ' ');
15197 }
15198
15199
15200
15201
15202
15203
15204
15205
15206
15207
15208
15209
15210
15211
15212
15213
15214
15215 static void
15216 display_tool_bar_line (struct it *it, int height)
15217 {
15218 struct glyph_row *row = it->glyph_row;
15219 int max_x = it->last_visible_x;
15220 struct glyph *last;
15221
15222
15223 clear_glyph_row (row);
15224 row->enabled_p = true;
15225 row->y = it->current_y;
15226
15227
15228
15229 it->start_of_box_run_p = true;
15230
15231 while (it->current_x < max_x)
15232 {
15233 int x, n_glyphs_before, i, nglyphs;
15234 struct it it_before;
15235
15236
15237 if (!get_next_display_element (it))
15238 {
15239
15240 if (height < 0 && !it->hpos)
15241 return;
15242 break;
15243 }
15244
15245
15246 n_glyphs_before = row->used[TEXT_AREA];
15247 it_before = *it;
15248
15249 PRODUCE_GLYPHS (it);
15250
15251 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15252 i = 0;
15253 x = it_before.current_x;
15254 while (i < nglyphs)
15255 {
15256 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15257
15258 if (x + glyph->pixel_width > max_x)
15259 {
15260
15261 row->used[TEXT_AREA] = n_glyphs_before;
15262 *it = it_before;
15263
15264
15265
15266 if (n_glyphs_before == 0
15267 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15268 break;
15269 goto out;
15270 }
15271
15272 ++it->hpos;
15273 x += glyph->pixel_width;
15274 ++i;
15275 }
15276
15277
15278
15279
15280
15281
15282 if (ITERATOR_AT_END_OF_LINE_P (it))
15283 {
15284 reseat_at_next_visible_line_start (it, false);
15285 break;
15286 }
15287
15288 if (ITERATOR_AT_END_P (it))
15289 break;
15290
15291 set_iterator_to_next (it, true);
15292 }
15293
15294 out:;
15295
15296 row->displays_text_p = row->used[TEXT_AREA] != 0;
15297
15298
15299
15300
15301
15302
15303
15304 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15305 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15306 it->face_id = DEFAULT_FACE_ID;
15307
15308 extend_face_to_end_of_line (it);
15309 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15310 last->right_box_line_p = true;
15311 if (last == row->glyphs[TEXT_AREA])
15312 last->left_box_line_p = true;
15313
15314
15315 if (height != -1
15316 && (height -= it->max_ascent + it->max_descent) > 0)
15317 {
15318
15319 height %= FRAME_LINE_HEIGHT (it->f);
15320 it->max_ascent += height / 2;
15321 it->max_descent += (height + 1) / 2;
15322 }
15323
15324 compute_line_metrics (it);
15325
15326
15327 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15328 {
15329 row->height = row->phys_height = it->last_visible_y - row->y;
15330 row->visible_height = row->height;
15331 row->ascent = row->phys_ascent = 0;
15332 row->extra_line_spacing = 0;
15333 }
15334
15335 row->full_width_p = true;
15336 row->continued_p = false;
15337 row->truncated_on_left_p = false;
15338 row->truncated_on_right_p = false;
15339
15340 it->current_x = it->hpos = 0;
15341 it->current_y += row->height;
15342 ++it->vpos;
15343 ++it->glyph_row;
15344 }
15345
15346
15347
15348
15349
15350
15351 static int
15352 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15353 {
15354 struct window *w = XWINDOW (f->tool_bar_window);
15355 struct it it;
15356
15357
15358
15359 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15360
15361
15362
15363 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15364 temp_row->reversed_p = false;
15365 it.first_visible_x = 0;
15366 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15367 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15368 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15369 it.paragraph_embedding = L2R;
15370
15371 while (!ITERATOR_AT_END_P (&it))
15372 {
15373 clear_glyph_row (temp_row);
15374 it.glyph_row = temp_row;
15375 display_tool_bar_line (&it, -1);
15376 }
15377 clear_glyph_row (temp_row);
15378
15379
15380 if (n_rows)
15381 *n_rows = it.vpos > 0 ? it.vpos : -1;
15382
15383 if (pixelwise)
15384 return it.current_y;
15385 else
15386 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15387 }
15388
15389 #endif
15390
15391 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15392 0, 2, 0,
15393 doc:
15394
15395 )
15396 (Lisp_Object frame, Lisp_Object pixelwise)
15397 {
15398 int height = 0;
15399
15400 #ifndef HAVE_EXT_TOOL_BAR
15401 struct frame *f = decode_any_frame (frame);
15402
15403 if (WINDOWP (f->tool_bar_window)
15404 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15405 {
15406 update_tool_bar (f, true);
15407 if (f->n_tool_bar_items)
15408 {
15409 build_desired_tool_bar_string (f);
15410 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15411 }
15412 }
15413 #endif
15414
15415 return make_fixnum (height);
15416 }
15417
15418 #ifndef HAVE_EXT_TOOL_BAR
15419
15420
15421
15422 static bool
15423 redisplay_tool_bar (struct frame *f)
15424 {
15425 struct window *w;
15426 struct it it;
15427 struct glyph_row *row;
15428 bool change_height_p;
15429
15430 change_height_p = false;
15431 f->tool_bar_redisplayed = true;
15432
15433
15434
15435
15436
15437 if (!WINDOWP (f->tool_bar_window)
15438 || (w = XWINDOW (f->tool_bar_window),
15439 WINDOW_TOTAL_LINES (w) == 0))
15440 {
15441
15442
15443
15444
15445
15446 f->tool_bar_resized = true;
15447
15448 return false;
15449 }
15450
15451
15452 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15453 it.first_visible_x = 0;
15454 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15455 row = it.glyph_row;
15456 row->reversed_p = false;
15457
15458
15459 build_desired_tool_bar_string (f);
15460 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15461 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15462
15463
15464
15465
15466
15467
15468
15469 it.paragraph_embedding = L2R;
15470
15471 if (f->n_tool_bar_rows == 0)
15472 {
15473 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15474
15475 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15476 {
15477 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15478 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15479 frame_default_tool_bar_height = new_height;
15480
15481 clear_glyph_matrix (w->desired_matrix);
15482 f->fonts_changed = true;
15483
15484
15485
15486
15487
15488
15489
15490 resize_frame_windows (f, FRAME_INNER_HEIGHT (f), false);
15491
15492 return true;
15493 }
15494 }
15495
15496
15497
15498 if (f->n_tool_bar_rows > 0)
15499 {
15500 int border, rows, height, extra;
15501
15502 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15503 border = XFIXNUM (Vtool_bar_border);
15504 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15505 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15506 else if (EQ (Vtool_bar_border, Qborder_width))
15507 border = f->border_width;
15508 else
15509 border = 0;
15510 if (border < 0)
15511 border = 0;
15512
15513 rows = f->n_tool_bar_rows;
15514
15515 if (f->tool_bar_wraps_p)
15516 {
15517
15518
15519
15520 while (!ITERATOR_AT_END_P (&it))
15521 display_tool_bar_line (&it, -1);
15522
15523
15524
15525
15526
15527
15528 if (it.current_y != it.last_visible_y)
15529 change_height_p = true;
15530 }
15531 else
15532 {
15533 height = max (1, (it.last_visible_y - border) / rows);
15534 extra = it.last_visible_y - border - height * rows;
15535
15536 while (it.current_y < it.last_visible_y)
15537 {
15538 int h = 0;
15539 if (extra > 0 && rows-- > 0)
15540 {
15541 h = (extra + rows - 1) / rows;
15542 extra -= h;
15543 }
15544
15545 display_tool_bar_line (&it, height + h);
15546 }
15547 }
15548 }
15549 else
15550 {
15551 while (it.current_y < it.last_visible_y)
15552 display_tool_bar_line (&it, 0);
15553 }
15554
15555
15556
15557 w->desired_matrix->no_scrolling_p = true;
15558 w->must_be_updated_p = true;
15559
15560 if (!NILP (Vauto_resize_tool_bars))
15561 {
15562
15563
15564 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15565 change_height_p = true;
15566
15567
15568
15569
15570
15571 row = it.glyph_row - 1;
15572
15573
15574
15575
15576 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15577 && row->height >= FRAME_LINE_HEIGHT (f))
15578 change_height_p = true;
15579
15580
15581
15582 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15583 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15584 change_height_p = true;
15585
15586
15587
15588 if (change_height_p)
15589 {
15590 int nrows;
15591 int new_height = tool_bar_height (f, &nrows, true);
15592
15593 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15594 && !f->minimize_tool_bar_window_p)
15595 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15596 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15597 f->minimize_tool_bar_window_p = false;
15598
15599 if (change_height_p)
15600 {
15601 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15602 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15603 frame_default_tool_bar_height = new_height;
15604 clear_glyph_matrix (w->desired_matrix);
15605 f->n_tool_bar_rows = nrows;
15606 f->fonts_changed = true;
15607
15608 return true;
15609 }
15610 }
15611 }
15612
15613 f->minimize_tool_bar_window_p = false;
15614
15615 return false;
15616 }
15617
15618
15619
15620
15621
15622
15623 static bool
15624 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15625 {
15626 Lisp_Object prop;
15627 ptrdiff_t charpos;
15628
15629
15630
15631
15632 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15633 charpos = max (0, charpos);
15634
15635
15636
15637
15638 prop = Fget_text_property (make_fixnum (charpos),
15639 Qmenu_item, f->current_tool_bar_string);
15640 if (! FIXNUMP (prop))
15641 return false;
15642 *prop_idx = XFIXNUM (prop);
15643 return true;
15644 }
15645
15646
15647
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657 static int
15658 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15659 int *hpos, int *vpos, int *prop_idx)
15660 {
15661 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15662 struct window *w = XWINDOW (f->tool_bar_window);
15663 int area;
15664
15665
15666 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15667 if (*glyph == NULL)
15668 return -1;
15669
15670
15671
15672 if (!tool_bar_item_info (f, *glyph, prop_idx))
15673 return -1;
15674
15675
15676 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15677 && *vpos >= hlinfo->mouse_face_beg_row
15678 && *vpos <= hlinfo->mouse_face_end_row
15679 && (*vpos > hlinfo->mouse_face_beg_row
15680 || *hpos >= hlinfo->mouse_face_beg_col)
15681 && (*vpos < hlinfo->mouse_face_end_row
15682 || *hpos < hlinfo->mouse_face_end_col
15683 || hlinfo->mouse_face_past_end))
15684 return 0;
15685
15686 return 1;
15687 }
15688
15689
15690
15691
15692
15693
15694
15695
15696 void
15697 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15698 int modifiers, Lisp_Object device)
15699 {
15700 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15701 struct window *w = XWINDOW (f->tool_bar_window);
15702 int hpos, vpos, prop_idx;
15703 struct glyph *glyph;
15704 Lisp_Object enabled_p;
15705 int ts;
15706
15707
15708
15709
15710
15711
15712
15713
15714 frame_to_window_pixel_xy (w, &x, &y);
15715 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15716 if (ts == -1
15717 || (ts != 0 && !NILP (Vmouse_highlight)))
15718 return;
15719
15720
15721
15722
15723 if (NILP (Vmouse_highlight) && !down_p)
15724 prop_idx = f->last_tool_bar_item;
15725
15726
15727 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15728 if (NILP (enabled_p))
15729 return;
15730
15731 if (down_p)
15732 {
15733
15734 if (!NILP (Vmouse_highlight))
15735 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15736 f->last_tool_bar_item = prop_idx;
15737 }
15738 else
15739 {
15740 Lisp_Object key, frame;
15741 struct input_event event;
15742 EVENT_INIT (event);
15743
15744
15745 if (!NILP (Vmouse_highlight))
15746 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15747
15748 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15749
15750 XSETFRAME (frame, f);
15751 event.kind = TOOL_BAR_EVENT;
15752 event.frame_or_window = frame;
15753 event.arg = key;
15754 event.modifiers = modifiers;
15755 event.device = device;
15756 kbd_buffer_store_event (&event);
15757 f->last_tool_bar_item = -1;
15758 }
15759 }
15760
15761 void
15762 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15763 int modifiers)
15764 {
15765 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15766 }
15767
15768
15769
15770
15771
15772 static void
15773 note_tool_bar_highlight (struct frame *f, int x, int y)
15774 {
15775 Lisp_Object window = f->tool_bar_window;
15776 struct window *w = XWINDOW (window);
15777 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15778 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15779 int hpos, vpos;
15780 struct glyph *glyph;
15781 struct glyph_row *row;
15782 int i;
15783 Lisp_Object enabled_p;
15784 int prop_idx;
15785 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15786 bool mouse_down_p;
15787 int rc;
15788
15789
15790
15791 if (x <= 0 || y <= 0)
15792 {
15793 clear_mouse_face (hlinfo);
15794 return;
15795 }
15796
15797 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15798 if (rc < 0)
15799 {
15800
15801 clear_mouse_face (hlinfo);
15802 return;
15803 }
15804 else if (rc == 0)
15805
15806 goto set_help_echo;
15807
15808 clear_mouse_face (hlinfo);
15809
15810
15811 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15812 && f == dpyinfo->last_mouse_frame);
15813
15814 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15815 return;
15816
15817 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15818
15819
15820 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15821 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15822 {
15823
15824
15825 row = MATRIX_ROW (w->current_matrix, vpos);
15826 for (i = x = 0; i < hpos; ++i)
15827 x += row->glyphs[TEXT_AREA][i].pixel_width;
15828
15829
15830 hlinfo->mouse_face_beg_col = hpos;
15831 hlinfo->mouse_face_beg_row = vpos;
15832 hlinfo->mouse_face_beg_x = x;
15833 hlinfo->mouse_face_past_end = false;
15834
15835 hlinfo->mouse_face_end_col = hpos + 1;
15836 hlinfo->mouse_face_end_row = vpos;
15837 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15838 hlinfo->mouse_face_window = window;
15839 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15840
15841
15842 show_mouse_face (hlinfo, draw);
15843 }
15844
15845 set_help_echo:
15846
15847
15848
15849 help_echo_object = help_echo_window = Qnil;
15850 help_echo_pos = -1;
15851 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15852 if (NILP (help_echo_string))
15853 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15854 }
15855
15856 #endif
15857
15858 #endif
15859
15860
15861
15862
15863
15864
15865
15866
15867
15868
15869
15870
15871
15872 static bool
15873 hscroll_window_tree (Lisp_Object window)
15874 {
15875 bool hscrolled_p = false;
15876 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15877 int hscroll_step_abs = 0;
15878 double hscroll_step_rel = 0;
15879
15880 if (hscroll_relative_p)
15881 {
15882 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15883 if (hscroll_step_rel < 0)
15884 {
15885 hscroll_relative_p = false;
15886 hscroll_step_abs = 0;
15887 }
15888 }
15889 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15890 {
15891 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15892 if (hscroll_step_abs < 0)
15893 hscroll_step_abs = 0;
15894 }
15895 else
15896 hscroll_step_abs = 0;
15897
15898 while (WINDOWP (window))
15899 {
15900 struct window *w = XWINDOW (window);
15901
15902 if (WINDOWP (w->contents))
15903 hscrolled_p |= hscroll_window_tree (w->contents);
15904 else if (w->cursor.vpos >= 0
15905
15906
15907
15908
15909
15910
15911 && !(w == XWINDOW (echo_area_window)
15912 && !NILP (echo_area_buffer[0])))
15913 {
15914 int h_margin;
15915 int text_area_width;
15916 struct glyph_row *cursor_row;
15917 struct glyph_row *bottom_row;
15918
15919 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15920 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15921 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15922 else
15923 cursor_row = bottom_row - 1;
15924
15925 if (!cursor_row->enabled_p)
15926 {
15927 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15928 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15929 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15930 else
15931 cursor_row = bottom_row - 1;
15932 }
15933 bool row_r2l_p = cursor_row->reversed_p;
15934 bool hscl = hscrolling_current_line_p (w);
15935 int x_offset = 0;
15936
15937
15938 if (!NILP (Vdisplay_line_numbers))
15939 {
15940 struct glyph *g;
15941 if (!row_r2l_p)
15942 {
15943 for (g = cursor_row->glyphs[TEXT_AREA];
15944 g < cursor_row->glyphs[TEXT_AREA]
15945 + cursor_row->used[TEXT_AREA];
15946 g++)
15947 {
15948 if (!(NILP (g->object) && g->charpos < 0))
15949 break;
15950 x_offset += g->pixel_width;
15951 }
15952 }
15953 else
15954 {
15955 for (g = cursor_row->glyphs[TEXT_AREA]
15956 + cursor_row->used[TEXT_AREA];
15957 g > cursor_row->glyphs[TEXT_AREA];
15958 g--)
15959 {
15960 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15961 break;
15962 x_offset += (g - 1)->pixel_width;
15963 }
15964 }
15965 }
15966 if (cursor_row->truncated_on_left_p)
15967 {
15968
15969 struct frame *f = XFRAME (WINDOW_FRAME (w));
15970 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
15971 }
15972
15973 text_area_width = window_box_width (w, TEXT_AREA);
15974
15975
15976 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
15977 * WINDOW_FRAME_COLUMN_WIDTH (w));
15978
15979
15980
15981 if (w->suspend_auto_hscroll
15982 && NILP (Fequal (Fwindow_point (window),
15983 Fwindow_old_point (window))))
15984 {
15985 w->suspend_auto_hscroll = false;
15986
15987
15988
15989
15990 if (w->min_hscroll == 0 && w->hscroll > 0
15991 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
15992 Qcurrent_line))
15993 SET_FRAME_GARBAGED (XFRAME (w->frame));
15994 }
15995
15996
15997 Fset_marker (w->old_pointm,
15998 ((w == XWINDOW (selected_window))
15999 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
16000 : Fmarker_position (w->pointm)),
16001 w->contents);
16002
16003 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
16004 && !w->suspend_auto_hscroll
16005
16006
16007
16008
16009
16010
16011 && (CHARPOS (cursor_row->start.pos)
16012 >= BUF_BEG (XBUFFER (w->contents)))
16013
16014
16015
16016
16017 && ((!row_r2l_p
16018 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
16019 || (cursor_row->enabled_p
16020 && cursor_row->truncated_on_right_p
16021 && (w->cursor.x >= text_area_width - h_margin))))
16022
16023
16024
16025
16026
16027
16028 || (row_r2l_p
16029 && ((cursor_row->enabled_p
16030
16031
16032
16033 && cursor_row->truncated_on_right_p
16034 && w->cursor.x <= h_margin)
16035 || (w->hscroll
16036 && (w->cursor.x >= (text_area_width - h_margin
16037 - x_offset)))))
16038
16039
16040
16041
16042
16043 || (hscl
16044 && w->hscroll != w->min_hscroll
16045 && !cursor_row->truncated_on_left_p)))
16046 {
16047 struct it it;
16048 ptrdiff_t hscroll;
16049 struct buffer *saved_current_buffer;
16050 ptrdiff_t pt;
16051 int wanted_x;
16052
16053
16054 saved_current_buffer = current_buffer;
16055 current_buffer = XBUFFER (w->contents);
16056
16057 if (w == XWINDOW (selected_window))
16058 pt = PT;
16059 else
16060 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
16061
16062
16063
16064 init_to_row_start (&it, w, cursor_row);
16065 if (hscl)
16066 it.first_visible_x = window_hscroll_limited (w, it.f)
16067 * FRAME_COLUMN_WIDTH (it.f);
16068 it.last_visible_x = DISP_INFINITY;
16069
16070 ptrdiff_t nchars = pt - IT_CHARPOS (it);
16071 if (current_buffer->long_line_optimizations_p
16072 && nchars > large_hscroll_threshold)
16073 {
16074
16075
16076
16077
16078 fast_move_it_horizontally (&it, nchars);
16079 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
16080 }
16081 else
16082 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
16083
16084
16085
16086
16087
16088
16089 if (it.method == GET_FROM_STRING && pt > 1)
16090 {
16091 init_to_row_start (&it, w, cursor_row);
16092 if (hscl)
16093 it.first_visible_x = (window_hscroll_limited (w, it.f)
16094 * FRAME_COLUMN_WIDTH (it.f));
16095 if (current_buffer->long_line_optimizations_p
16096 && nchars > large_hscroll_threshold)
16097 {
16098 fast_move_it_horizontally (&it, nchars - 1);
16099 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
16100 }
16101 else
16102 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
16103 }
16104 current_buffer = saved_current_buffer;
16105
16106
16107 if (!hscroll_relative_p && hscroll_step_abs == 0)
16108 hscroll = max (0, (it.current_x
16109 - (ITERATOR_AT_END_OF_LINE_P (&it)
16110 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
16111 : (text_area_width / 2))))
16112 / FRAME_COLUMN_WIDTH (it.f);
16113 else if ((!row_r2l_p
16114 && w->cursor.x >= text_area_width - h_margin)
16115 || (row_r2l_p && w->cursor.x <= h_margin))
16116 {
16117 if (hscroll_relative_p)
16118 wanted_x = text_area_width * (1 - hscroll_step_rel)
16119 - h_margin;
16120 else
16121 wanted_x = text_area_width
16122 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16123 - h_margin;
16124 hscroll
16125 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16126 }
16127 else
16128 {
16129 if (hscroll_relative_p)
16130 wanted_x =
16131 text_area_width * hscroll_step_rel + h_margin + x_offset;
16132 else
16133 wanted_x =
16134 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16135 + h_margin + x_offset;
16136 hscroll
16137 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16138 }
16139 hscroll = max (hscroll, w->min_hscroll);
16140
16141
16142
16143
16144 if (w->hscroll != hscroll
16145
16146
16147
16148
16149 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16150 {
16151 struct buffer *b = XBUFFER (w->contents);
16152 b->prevent_redisplay_optimizations_p = true;
16153 w->hscroll = hscroll;
16154 hscrolled_p = true;
16155 }
16156 }
16157 }
16158
16159 window = w->next;
16160 }
16161
16162
16163 return hscrolled_p;
16164 }
16165
16166
16167
16168
16169
16170
16171
16172
16173 static bool
16174 hscroll_windows (Lisp_Object window)
16175 {
16176 bool hscrolled_p = hscroll_window_tree (window);
16177 if (hscrolled_p)
16178 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16179 return hscrolled_p;
16180 }
16181
16182
16183
16184
16185
16186
16187
16188
16189
16190
16191 #ifdef GLYPH_DEBUG
16192
16193
16194
16195 static int debug_first_unchanged_at_end_vpos;
16196 static int debug_last_unchanged_at_beg_vpos;
16197
16198
16199
16200 static int debug_dvpos, debug_dy;
16201
16202
16203
16204 static ptrdiff_t debug_delta, debug_delta_bytes;
16205
16206
16207
16208
16209 static ptrdiff_t debug_end_vpos;
16210
16211
16212
16213
16214
16215 static void debug_method_add (struct window *, char const *, ...)
16216 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16217
16218 static void
16219 debug_method_add (struct window *w, char const *fmt, ...)
16220 {
16221 void *ptr = w;
16222 char *method = w->desired_matrix->method;
16223 int len = strlen (method);
16224 int size = sizeof w->desired_matrix->method;
16225 int remaining = size - len - 1;
16226 va_list ap;
16227
16228 if (len && remaining)
16229 {
16230 method[len] = '|';
16231 --remaining, ++len;
16232 }
16233
16234 va_start (ap, fmt);
16235 vsnprintf (method + len, remaining + 1, fmt, ap);
16236 va_end (ap);
16237
16238 if (trace_redisplay_p)
16239 fprintf (stderr, "%p (%s): %s\n",
16240 ptr,
16241 ((BUFFERP (w->contents)
16242 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16243 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16244 : "no buffer"),
16245 method + len);
16246 }
16247
16248 #endif
16249
16250
16251
16252
16253
16254
16255
16256 static bool
16257 text_outside_line_unchanged_p (struct window *w,
16258 ptrdiff_t start, ptrdiff_t end)
16259 {
16260 bool unchanged_p = true;
16261
16262
16263 if (window_outdated (w))
16264 {
16265
16266 if (GPT < start || Z - GPT < end)
16267 unchanged_p = false;
16268
16269
16270 if (unchanged_p
16271 && (BEG_UNCHANGED < start - 1
16272 || END_UNCHANGED < end))
16273 unchanged_p = false;
16274
16275
16276
16277 if (unchanged_p
16278 && FIXNUMP (BVAR (current_buffer, selective_display))
16279 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16280 && (BEG_UNCHANGED < start || GPT <= start))
16281 unchanged_p = false;
16282
16283
16284
16285
16286
16287
16288
16289
16290 if (unchanged_p)
16291 {
16292 if (BEG + BEG_UNCHANGED == start
16293 && overlay_touches_p (start))
16294 unchanged_p = false;
16295 if (END_UNCHANGED == end
16296 && overlay_touches_p (Z - end))
16297 unchanged_p = false;
16298 }
16299
16300
16301
16302
16303
16304
16305
16306
16307 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16308 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16309 unchanged_p = false;
16310 }
16311
16312 return unchanged_p;
16313 }
16314
16315
16316
16317
16318
16319
16320
16321
16322
16323 void
16324 redisplay (void)
16325 {
16326 redisplay_internal ();
16327 }
16328
16329
16330 static Lisp_Object
16331 overlay_arrow_string_or_property (Lisp_Object var)
16332 {
16333 Lisp_Object val;
16334
16335 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16336 return val;
16337
16338 return Voverlay_arrow_string;
16339 }
16340
16341
16342 static bool
16343 overlay_arrow_in_current_buffer_p (void)
16344 {
16345 Lisp_Object vlist;
16346
16347 for (vlist = Voverlay_arrow_variable_list;
16348 CONSP (vlist);
16349 vlist = XCDR (vlist))
16350 {
16351 Lisp_Object var = XCAR (vlist);
16352 Lisp_Object val;
16353
16354 if (!SYMBOLP (var))
16355 continue;
16356 val = find_symbol_value (var);
16357 if (MARKERP (val)
16358 && current_buffer == XMARKER (val)->buffer)
16359 return true;
16360 }
16361 return false;
16362 }
16363
16364
16365
16366
16367
16368
16369
16370 static bool
16371 overlay_arrows_changed_p (bool set_redisplay)
16372 {
16373 Lisp_Object vlist;
16374 bool changed = false;
16375
16376 for (vlist = Voverlay_arrow_variable_list;
16377 CONSP (vlist);
16378 vlist = XCDR (vlist))
16379 {
16380 Lisp_Object var = XCAR (vlist);
16381 Lisp_Object val, pstr;
16382
16383 if (!SYMBOLP (var))
16384 continue;
16385 val = find_symbol_value (var);
16386 if (!MARKERP (val))
16387 continue;
16388 if (! EQ (Fmarker_position (val),
16389
16390
16391 Fget (var, Qlast_arrow_position))
16392 || ! (pstr = overlay_arrow_string_or_property (var),
16393 EQ (pstr, Fget (var, Qlast_arrow_string))))
16394 {
16395 struct buffer *buf = XMARKER (val)->buffer;
16396
16397 if (set_redisplay)
16398 {
16399 if (buf)
16400 bset_redisplay (buf);
16401 changed = true;
16402 }
16403 else
16404 return true;
16405 }
16406 }
16407 return changed;
16408 }
16409
16410
16411
16412 static void
16413 update_overlay_arrows (int up_to_date)
16414 {
16415 Lisp_Object vlist;
16416
16417 for (vlist = Voverlay_arrow_variable_list;
16418 CONSP (vlist);
16419 vlist = XCDR (vlist))
16420 {
16421 Lisp_Object var = XCAR (vlist);
16422
16423 if (!SYMBOLP (var))
16424 continue;
16425
16426 if (up_to_date > 0)
16427 {
16428 Lisp_Object val = find_symbol_value (var);
16429 if (!MARKERP (val))
16430 continue;
16431 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16432 Fput (var, Qlast_arrow_string,
16433 overlay_arrow_string_or_property (var));
16434 }
16435 else if (up_to_date < 0
16436 || !NILP (Fget (var, Qlast_arrow_position)))
16437 {
16438 Fput (var, Qlast_arrow_position, Qt);
16439 Fput (var, Qlast_arrow_string, Qt);
16440 }
16441 }
16442 }
16443
16444
16445
16446
16447
16448
16449 static Lisp_Object
16450 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16451 {
16452 Lisp_Object vlist;
16453
16454 for (vlist = Voverlay_arrow_variable_list;
16455 CONSP (vlist);
16456 vlist = XCDR (vlist))
16457 {
16458 Lisp_Object var = XCAR (vlist);
16459 Lisp_Object val;
16460
16461 if (!SYMBOLP (var))
16462 continue;
16463
16464 val = find_symbol_value (var);
16465
16466 if (MARKERP (val)
16467 && current_buffer == XMARKER (val)->buffer
16468 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16469 {
16470 if (FRAME_WINDOW_P (it->f)
16471
16472
16473 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16474 {
16475 #ifdef HAVE_WINDOW_SYSTEM
16476 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16477 {
16478 int fringe_bitmap = lookup_fringe_bitmap (val);
16479 if (fringe_bitmap != 0)
16480 return make_fixnum (fringe_bitmap);
16481 }
16482 #endif
16483 return make_fixnum (-1);
16484 }
16485 return overlay_arrow_string_or_property (var);
16486 }
16487 }
16488
16489 return Qnil;
16490 }
16491
16492
16493
16494
16495
16496 static bool
16497 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16498 struct buffer *buf, ptrdiff_t pt)
16499 {
16500 ptrdiff_t start, end;
16501 Lisp_Object prop;
16502 Lisp_Object buffer;
16503
16504 XSETBUFFER (buffer, buf);
16505
16506
16507 if (prev_buf == buf)
16508 {
16509 if (prev_pt == pt)
16510
16511 return false;
16512
16513 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16514 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16515 && composition_valid_p (start, end, prop)
16516 && start < prev_pt && end > prev_pt)
16517
16518
16519 return (pt <= start || pt >= end);
16520 }
16521
16522
16523 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16524 && find_composition (pt, -1, &start, &end, &prop, buffer)
16525 && composition_valid_p (start, end, prop)
16526 && start < pt && end > pt);
16527 }
16528
16529
16530
16531 static void
16532 reconsider_clip_changes (struct window *w)
16533 {
16534 struct buffer *b = XBUFFER (w->contents);
16535
16536 if (b->clip_changed
16537 && w->window_end_valid
16538 && w->current_matrix->buffer == b
16539 && w->current_matrix->zv == BUF_ZV (b)
16540 && w->current_matrix->begv == BUF_BEGV (b))
16541 b->clip_changed = false;
16542
16543
16544
16545
16546
16547 if (!b->clip_changed && w->window_end_valid)
16548 {
16549 ptrdiff_t pt = (w == XWINDOW (selected_window)
16550 ? PT : marker_position (w->pointm));
16551
16552 if ((w->current_matrix->buffer != b || pt != w->last_point)
16553 && check_point_in_composition (w->current_matrix->buffer,
16554 w->last_point, b, pt))
16555 b->clip_changed = true;
16556 }
16557 }
16558
16559 static void
16560 propagate_buffer_redisplay (void)
16561 {
16562
16563
16564
16565
16566
16567
16568
16569
16570
16571 Lisp_Object ws = window_list ();
16572 for (; CONSP (ws); ws = XCDR (ws))
16573 {
16574 struct window *thisw = XWINDOW (XCAR (ws));
16575 struct buffer *thisb = XBUFFER (thisw->contents);
16576 if (thisb->text->redisplay)
16577 thisw->redisplay = true;
16578 }
16579 }
16580
16581 #define STOP_POLLING \
16582 do { if (! polling_stopped_here) stop_polling (); \
16583 polling_stopped_here = true; } while (false)
16584
16585 #define RESUME_POLLING \
16586 do { if (polling_stopped_here) start_polling (); \
16587 polling_stopped_here = false; } while (false)
16588
16589
16590
16591
16592 static void
16593 redisplay_internal (void)
16594 {
16595 struct window *w = XWINDOW (selected_window);
16596 struct window *sw;
16597 struct frame *fr;
16598 bool pending;
16599 bool must_finish = false, match_p;
16600 struct text_pos tlbufpos, tlendpos;
16601 int number_of_visible_frames;
16602 struct frame *sf;
16603 bool polling_stopped_here = false;
16604 Lisp_Object tail, frame;
16605
16606
16607
16608
16609 enum { MAX_HSCROLL_RETRIES = 16 };
16610 int hscroll_retries = 0;
16611
16612
16613
16614
16615
16616
16617 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16618 int garbaged_frame_retries = 0;
16619
16620
16621
16622
16623 bool consider_all_windows_p;
16624
16625
16626 bool update_miniwindow_p = false;
16627
16628 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16629
16630
16631
16632
16633 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16634 && redisplay_skip_initial_frame)
16635 || !NILP (Vinhibit_redisplay))
16636 return;
16637
16638
16639
16640
16641 fr = XFRAME (w->frame);
16642 sf = SELECTED_FRAME ();
16643
16644 if (!fr->glyphs_initialized_p)
16645 return;
16646
16647 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16648 if (popup_activated ())
16649 return;
16650 #endif
16651
16652 #if defined (HAVE_HAIKU)
16653 if (popup_activated_p)
16654 return;
16655 #endif
16656
16657
16658 if (redisplaying_p)
16659 return;
16660
16661
16662
16663 specpdl_ref count = SPECPDL_INDEX ();
16664 record_unwind_protect_void (unwind_redisplay);
16665 redisplaying_p = true;
16666 block_buffer_flips ();
16667 specbind (Qinhibit_free_realized_faces, Qnil);
16668
16669
16670 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16671
16672 FOR_EACH_FRAME (tail, frame)
16673 XFRAME (frame)->already_hscrolled_p = false;
16674
16675 reset_outermost_restrictions ();
16676
16677 retry:
16678
16679 sw = w;
16680
16681 pending = false;
16682 forget_escape_and_glyphless_faces ();
16683
16684 inhibit_free_realized_faces = false;
16685
16686
16687
16688
16689 if (face_change)
16690 windows_or_buffers_changed = 47;
16691
16692 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16693 && FRAME_TTY (sf)->previous_frame != sf)
16694 {
16695
16696
16697
16698 SET_FRAME_GARBAGED (sf);
16699 #if !defined DOS_NT && !defined HAVE_ANDROID
16700 set_tty_color_mode (FRAME_TTY (sf), sf);
16701 #endif
16702 FRAME_TTY (sf)->previous_frame = sf;
16703 }
16704
16705
16706
16707
16708 number_of_visible_frames = 0;
16709
16710 FOR_EACH_FRAME (tail, frame)
16711 {
16712 struct frame *f = XFRAME (frame);
16713
16714 if (FRAME_REDISPLAY_P (f))
16715 {
16716 ++number_of_visible_frames;
16717
16718 if (f->fonts_changed)
16719 {
16720 adjust_frame_glyphs (f);
16721
16722
16723
16724
16725
16726
16727 SET_FRAME_GARBAGED (f);
16728 f->fonts_changed = false;
16729 }
16730
16731
16732 if (f != sf && f->cursor_type_changed)
16733 fset_redisplay (f);
16734 }
16735 clear_desired_matrices (f);
16736 }
16737
16738
16739 do_pending_window_change (true);
16740
16741
16742 clear_garbaged_frames ();
16743
16744
16745 if (NILP (Vmemory_full))
16746 prepare_menu_bars ();
16747
16748
16749
16750
16751
16752 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16753 sw = w;
16754
16755 reconsider_clip_changes (w);
16756
16757
16758 match_p = XBUFFER (w->contents) == current_buffer;
16759 if (match_p)
16760 {
16761
16762 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16763 w->update_mode_line = true;
16764
16765 if (mode_line_update_needed (w))
16766 w->update_mode_line = true;
16767
16768
16769
16770
16771 if (current_buffer->clip_changed)
16772 bset_update_mode_line (current_buffer);
16773 }
16774
16775
16776
16777
16778
16779
16780 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16781 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16782 || (message_cleared_p
16783 && minibuf_level == 0
16784
16785
16786 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16787 {
16788 echo_area_display (false);
16789
16790 if (message_cleared_p)
16791 update_miniwindow_p = true;
16792
16793 must_finish = true;
16794
16795
16796
16797
16798
16799 if (!display_last_displayed_message_p)
16800 message_cleared_p = false;
16801 }
16802 else if (EQ (selected_window, minibuf_window)
16803 && (current_buffer->clip_changed || window_outdated (w))
16804 && resize_mini_window (w, false))
16805 {
16806
16807
16808 must_finish = true;
16809
16810
16811
16812
16813 clear_garbaged_frames ();
16814 }
16815
16816 if (!NILP (Vrun_hooks))
16817 run_window_change_functions ();
16818
16819 if (windows_or_buffers_changed && !update_mode_lines)
16820
16821
16822
16823 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16824 ? REDISPLAY_SOME : 32);
16825
16826
16827
16828
16829
16830 overlay_arrows_changed_p (true);
16831
16832 consider_all_windows_p = (update_mode_lines
16833 || windows_or_buffers_changed);
16834
16835 #define AINC(a,i) \
16836 { \
16837 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16838 if (FIXNUMP (entry)) \
16839 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16840 }
16841
16842 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16843 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16844
16845
16846
16847
16848
16849 tlbufpos = this_line_start_pos;
16850 tlendpos = this_line_end_pos;
16851 if (!consider_all_windows_p
16852 && CHARPOS (tlbufpos) > 0
16853 && !w->update_mode_line
16854 && !current_buffer->clip_changed
16855 && !current_buffer->prevent_redisplay_optimizations_p
16856 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16857 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16858 && !XFRAME (w->frame)->cursor_type_changed
16859 && !XFRAME (w->frame)->face_change
16860
16861 && this_line_buffer == current_buffer
16862 && match_p
16863 && !w->force_start
16864 && !w->optional_new_start
16865
16866 && PT >= CHARPOS (tlbufpos)
16867 && PT <= Z - CHARPOS (tlendpos)
16868
16869
16870
16871
16872
16873
16874 && (NILP (Vdisplay_line_numbers)
16875 || EQ (Vdisplay_line_numbers, Qvisual))
16876
16877
16878 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16879 CHARPOS (tlendpos)))
16880 {
16881 if (CHARPOS (tlbufpos) > BEGV
16882 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16883 && (CHARPOS (tlbufpos) == ZV
16884 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16885
16886 goto cancel;
16887 else if (window_outdated (w) || MINI_WINDOW_P (w))
16888 {
16889
16890
16891
16892
16893
16894
16895
16896
16897
16898
16899
16900
16901
16902
16903
16904 struct it it;
16905 int line_height_before = this_line_pixel_height;
16906
16907
16908
16909 start_display (&it, w, tlbufpos);
16910
16911
16912 if (it.current_x != this_line_start_x)
16913 goto cancel;
16914
16915
16916
16917
16918 if (it.sp > 1
16919 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16920 goto cancel;
16921 redisplay_trace ("trying display optimization 1\n");
16922 w->cursor.vpos = -1;
16923 overlay_arrow_seen = false;
16924 it.vpos = this_line_vpos;
16925 it.current_y = this_line_y;
16926 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16927 display_line (&it, -1);
16928
16929
16930
16931 if (w->cursor.vpos >= 0
16932
16933
16934 && CHARPOS (this_line_start_pos)
16935
16936 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16937
16938
16939 && this_line_pixel_height == line_height_before
16940
16941
16942
16943
16944 && !hscrolling_current_line_p (w))
16945 {
16946
16947
16948 if (it.current_y < it.last_visible_y)
16949 {
16950 struct glyph_row *row
16951 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16952 ptrdiff_t delta, delta_bytes;
16953
16954
16955
16956
16957
16958
16959 delta = (Z
16960 - CHARPOS (tlendpos)
16961 - MATRIX_ROW_START_CHARPOS (row));
16962 delta_bytes = (Z_BYTE
16963 - BYTEPOS (tlendpos)
16964 - MATRIX_ROW_START_BYTEPOS (row));
16965
16966 increment_matrix_positions (w->current_matrix,
16967 this_line_vpos + 1,
16968 w->current_matrix->nrows,
16969 delta, delta_bytes);
16970 }
16971
16972
16973
16974
16975 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
16976 {
16977 if (w->window_end_vpos < this_line_vpos)
16978 w->window_end_vpos = this_line_vpos;
16979 }
16980 else if (w->window_end_vpos == this_line_vpos
16981 && this_line_vpos > 0)
16982 w->window_end_vpos = this_line_vpos - 1;
16983 w->window_end_valid = false;
16984
16985
16986 w->desired_matrix->no_scrolling_p = true;
16987
16988 #ifdef GLYPH_DEBUG
16989 *w->desired_matrix->method = 0;
16990 debug_method_add (w, "optimization 1");
16991 #endif
16992 #ifdef HAVE_WINDOW_SYSTEM
16993 update_window_fringes (w, false);
16994 #endif
16995 goto update;
16996 }
16997 else
16998 goto cancel;
16999 }
17000 else if (
17001 PT == w->last_point
17002
17003
17004
17005
17006 && 0 <= w->cursor.vpos
17007 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
17008 {
17009 if (!must_finish)
17010 {
17011 do_pending_window_change (true);
17012
17013 if (WINDOWP (selected_window)
17014 && (w = XWINDOW (selected_window)) != sw)
17015 goto retry;
17016
17017
17018
17019 if (w->cursor_off_p == w->last_cursor_off_p)
17020 goto end_of_redisplay;
17021 }
17022 goto update;
17023 }
17024
17025
17026 else if (NILP (Vshow_trailing_whitespace)
17027 && !cursor_in_echo_area
17028 && !composition_break_at_point)
17029 {
17030 struct it it;
17031 struct glyph_row *row;
17032
17033
17034
17035
17036 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
17037 NULL, DEFAULT_FACE_ID);
17038 it.current_x = this_line_start_x;
17039 it.current_y = this_line_y;
17040 it.vpos = this_line_vpos;
17041
17042 if (current_buffer->long_line_optimizations_p
17043 && it.line_wrap == TRUNCATE
17044 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
17045 {
17046
17047
17048
17049 reseat_at_next_visible_line_start (&it, false);
17050 if (IT_CHARPOS (it) <= PT)
17051 it.vpos = this_line_vpos + 1;
17052 }
17053 else
17054 {
17055
17056
17057 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
17058 }
17059
17060 if (it.vpos == this_line_vpos
17061 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
17062 row->enabled_p))
17063 {
17064 eassert (this_line_vpos == it.vpos);
17065 eassert (this_line_y == it.current_y);
17066 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
17067 if (cursor_row_fully_visible_p (w, false, true, false))
17068 {
17069 #ifdef GLYPH_DEBUG
17070 *w->desired_matrix->method = 0;
17071 debug_method_add (w, "optimization 3");
17072 #endif
17073 goto update;
17074 }
17075 else
17076 goto cancel;
17077 }
17078 else
17079 goto cancel;
17080 }
17081
17082 cancel:
17083
17084 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
17085 }
17086
17087 CHARPOS (this_line_start_pos) = 0;
17088 ++clear_face_cache_count;
17089 #ifdef HAVE_WINDOW_SYSTEM
17090 ++clear_image_cache_count;
17091 #endif
17092
17093
17094
17095
17096
17097
17098 if (consider_all_windows_p)
17099 {
17100 FOR_EACH_FRAME (tail, frame)
17101 XFRAME (frame)->updated_p = false;
17102
17103 propagate_buffer_redisplay ();
17104
17105 FOR_EACH_FRAME (tail, frame)
17106 {
17107 struct frame *f = XFRAME (frame);
17108
17109
17110
17111 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
17112 && !EQ (FRAME_TTY (f)->top_frame, frame))
17113 continue;
17114
17115 retry_frame:
17116 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17117 {
17118 bool gcscrollbars
17119
17120 = f->redisplay || !REDISPLAY_SOME_P ();
17121 bool f_redisplay_flag = f->redisplay;
17122
17123
17124
17125
17126 if (!FRAME_LIVE_P (f))
17127 continue;
17128
17129
17130
17131 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17132 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17133
17134 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17135 {
17136
17137
17138
17139
17140
17141
17142
17143 f->inhibit_clear_image_cache = true;
17144 redisplay_windows (FRAME_ROOT_WINDOW (f));
17145 }
17146
17147
17148 else if (!REDISPLAY_SOME_P ())
17149 f->redisplay = true;
17150
17151
17152 if (!FRAME_LIVE_P (f))
17153 continue;
17154
17155
17156
17157 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17158 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17159
17160 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17161 {
17162
17163 if (f->fonts_changed)
17164 {
17165 adjust_frame_glyphs (f);
17166
17167
17168
17169 SET_FRAME_GARBAGED (f);
17170 f->fonts_changed = false;
17171 goto retry_frame;
17172 }
17173
17174
17175 if (!f->already_hscrolled_p)
17176 {
17177 f->already_hscrolled_p = true;
17178 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17179 && hscroll_windows (f->root_window))
17180 {
17181 hscroll_retries++;
17182 goto retry_frame;
17183 }
17184 }
17185
17186
17187
17188
17189
17190
17191
17192
17193
17194
17195
17196
17197 if (!f_redisplay_flag && f->redisplay)
17198 goto retry_frame;
17199
17200
17201
17202
17203
17204
17205
17206
17207
17208 if (FRAME_GARBAGED_P (f)
17209 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17210 goto retry;
17211
17212 #ifdef HAVE_WINDOW_SYSTEM
17213 if (FRAME_WINDOW_P (f)
17214 && FRAME_RIF (f)->clear_under_internal_border)
17215 FRAME_RIF (f)->clear_under_internal_border (f);
17216 #endif
17217
17218
17219
17220 if (interrupt_input)
17221 unrequest_sigio ();
17222 STOP_POLLING;
17223
17224 pending |= update_frame (f, false, false);
17225
17226
17227
17228
17229
17230
17231
17232 if (FRAME_GARBAGED_P (f))
17233 {
17234 fset_redisplay (f);
17235 f->garbaged = false;
17236 goto retry_frame;
17237 }
17238 f->cursor_type_changed = false;
17239 f->updated_p = true;
17240 f->inhibit_clear_image_cache = false;
17241 }
17242 }
17243 }
17244
17245 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17246
17247 if (!pending)
17248 {
17249
17250
17251
17252 FOR_EACH_FRAME (tail, frame)
17253 {
17254 struct frame *f = XFRAME (frame);
17255 if (f->updated_p)
17256 {
17257 f->redisplay = false;
17258 f->garbaged = false;
17259 mark_window_display_accurate (f->root_window, true);
17260 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17261 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17262 }
17263 }
17264 }
17265 }
17266 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17267 {
17268 sf->inhibit_clear_image_cache = true;
17269 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17270
17271
17272 internal_condition_case_1 (redisplay_window_1, selected_window,
17273 list_of_error,
17274 redisplay_window_error);
17275 if (update_miniwindow_p)
17276 {
17277 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17278
17279 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17280 internal_condition_case_1 (redisplay_window_1, mini_window,
17281 list_of_error,
17282 redisplay_window_error);
17283 }
17284
17285
17286
17287 update:
17288
17289
17290
17291 if (sf->fonts_changed || sf->redisplay)
17292 {
17293 if (sf->redisplay)
17294 {
17295
17296
17297
17298
17299
17300
17301 windows_or_buffers_changed = 50;
17302 }
17303 goto retry;
17304 }
17305
17306
17307
17308 inhibit_free_realized_faces = true;
17309
17310
17311
17312
17313 if (interrupt_input)
17314 unrequest_sigio ();
17315 STOP_POLLING;
17316
17317 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17318 {
17319 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17320 && hscroll_windows (selected_window))
17321 {
17322 hscroll_retries++;
17323 goto retry;
17324 }
17325
17326 XWINDOW (selected_window)->must_be_updated_p = true;
17327 pending = update_frame (sf, false, false);
17328 sf->cursor_type_changed = false;
17329 sf->inhibit_clear_image_cache = false;
17330 }
17331
17332
17333
17334
17335
17336
17337 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17338 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17339
17340 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17341 {
17342 XWINDOW (mini_window)->must_be_updated_p = true;
17343 pending |= update_frame (mini_frame, false, false);
17344 mini_frame->cursor_type_changed = false;
17345 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17346 && hscroll_windows (mini_window))
17347 {
17348 hscroll_retries++;
17349 goto retry;
17350 }
17351 }
17352 }
17353
17354
17355
17356 if (pending)
17357 {
17358
17359
17360
17361 CHARPOS (this_line_start_pos) = 0;
17362
17363
17364 update_overlay_arrows (0);
17365
17366
17367
17368 if (!WINDOW_FULL_WIDTH_P (w)
17369 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17370 update_mode_lines = 36;
17371 }
17372 else
17373 {
17374 if (!consider_all_windows_p)
17375 {
17376
17377
17378 if (XBUFFER (w->contents)->text->redisplay
17379 && buffer_window_count (XBUFFER (w->contents)) > 1)
17380
17381
17382 propagate_buffer_redisplay ();
17383 mark_window_display_accurate_1 (w, true);
17384
17385
17386 update_overlay_arrows (1);
17387
17388 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17389 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17390 }
17391
17392 update_mode_lines = 0;
17393 windows_or_buffers_changed = 0;
17394 }
17395
17396
17397
17398
17399
17400 if (interrupt_input)
17401 request_sigio ();
17402 RESUME_POLLING;
17403
17404
17405
17406
17407
17408
17409
17410 if (!pending)
17411 {
17412 int new_count = 0;
17413
17414 FOR_EACH_FRAME (tail, frame)
17415 {
17416 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17417 new_count++;
17418 }
17419
17420 if (new_count != number_of_visible_frames)
17421 windows_or_buffers_changed = 52;
17422 }
17423
17424
17425 do_pending_window_change (true);
17426
17427
17428
17429 if ((windows_or_buffers_changed && !pending)
17430 || (WINDOWP (selected_window)
17431 && (w = XWINDOW (selected_window)) != sw))
17432 goto retry;
17433
17434
17435
17436
17437
17438
17439
17440 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17441 {
17442 clear_face_cache (false);
17443 clear_face_cache_count = 0;
17444 }
17445
17446 #ifdef HAVE_WINDOW_SYSTEM
17447 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17448 {
17449 clear_image_caches (Qnil);
17450 clear_image_cache_count = 0;
17451 }
17452 #endif
17453
17454 end_of_redisplay:
17455 #ifdef HAVE_NS
17456 ns_set_doc_edited ();
17457 #endif
17458 if (interrupt_input && interrupts_deferred)
17459 request_sigio ();
17460
17461
17462
17463 if (max_redisplay_ticks > 0)
17464 update_redisplay_ticks (0, NULL);
17465
17466 unbind_to (count, Qnil);
17467 RESUME_POLLING;
17468 }
17469
17470 static void
17471 unwind_redisplay_preserve_echo_area (void)
17472 {
17473 unblock_buffer_flips ();
17474 }
17475
17476
17477
17478
17479
17480
17481
17482
17483
17484
17485
17486
17487 void
17488 redisplay_preserve_echo_area (int from_where)
17489 {
17490 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17491
17492 block_input ();
17493 specpdl_ref count = SPECPDL_INDEX ();
17494 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17495 block_buffer_flips ();
17496 unblock_input ();
17497
17498 if (!NILP (echo_area_buffer[1]))
17499 {
17500
17501
17502 display_last_displayed_message_p = true;
17503 redisplay_internal ();
17504 display_last_displayed_message_p = false;
17505 }
17506 else
17507 redisplay_internal ();
17508
17509 flush_frame (SELECTED_FRAME ());
17510 unbind_to (count, Qnil);
17511 }
17512
17513
17514
17515
17516 static void
17517 unwind_redisplay (void)
17518 {
17519 redisplaying_p = false;
17520 unblock_buffer_flips ();
17521 }
17522
17523
17524
17525 void
17526 unwind_display_working_on_window (void)
17527 {
17528 display_working_on_window_p = false;
17529 }
17530
17531
17532
17533
17534
17535
17536 static void
17537 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17538 {
17539 struct buffer *b = XBUFFER (w->contents);
17540 #ifdef HAVE_TEXT_CONVERSION
17541 ptrdiff_t prev_point, prev_mark;
17542 #endif
17543
17544 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17545 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17546 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17547
17548 if (accurate_p)
17549 {
17550 b->clip_changed = false;
17551 b->prevent_redisplay_optimizations_p = false;
17552 eassert (buffer_window_count (b) > 0);
17553
17554
17555
17556 b->text->redisplay = false;
17557
17558 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17559 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17560 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17561 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17562
17563 w->current_matrix->buffer = b;
17564 w->current_matrix->begv = BUF_BEGV (b);
17565 w->current_matrix->zv = BUF_ZV (b);
17566 w->current_matrix->header_line_p = window_wants_header_line (w);
17567 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17568
17569 w->last_cursor_vpos = w->cursor.vpos;
17570 w->last_cursor_off_p = w->cursor_off_p;
17571
17572 #ifdef HAVE_TEXT_CONVERSION
17573 prev_point = w->last_point;
17574 prev_mark = w->last_mark;
17575 #endif
17576
17577 if (w == XWINDOW (selected_window))
17578 w->last_point = BUF_PT (b);
17579 else
17580 w->last_point = marker_position (w->pointm);
17581
17582
17583
17584
17585
17586 if (XMARKER (BVAR (b, mark))->buffer == b
17587 && !NILP (BVAR (b, mark_active)))
17588 w->last_mark = marker_position (BVAR (b, mark));
17589 else
17590 w->last_mark = -1;
17591
17592 #ifdef HAVE_TEXT_CONVERSION
17593
17594 w->ephemeral_last_point = w->last_point;
17595
17596
17597
17598
17599
17600
17601
17602
17603
17604
17605
17606
17607
17608
17609
17610 if ((prev_point != w->last_point
17611 || prev_mark != w->last_mark)
17612 && FRAME_WINDOW_P (WINDOW_XFRAME (w))
17613 && w == XWINDOW (WINDOW_XFRAME (w)->selected_window))
17614 report_point_change (WINDOW_XFRAME (w), w, b);
17615 #endif
17616
17617 w->window_end_valid = true;
17618 w->update_mode_line = false;
17619 w->preserve_vscroll_p = false;
17620 }
17621
17622 w->redisplay = !accurate_p;
17623 }
17624
17625
17626
17627
17628
17629
17630
17631 void
17632 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17633 {
17634 struct window *w;
17635
17636 for (; !NILP (window); window = w->next)
17637 {
17638 w = XWINDOW (window);
17639 if (WINDOWP (w->contents))
17640 mark_window_display_accurate (w->contents, accurate_p);
17641 else
17642 mark_window_display_accurate_1 (w, accurate_p);
17643 }
17644
17645 if (accurate_p)
17646 update_overlay_arrows (1);
17647 else
17648
17649
17650
17651 update_overlay_arrows (-1);
17652 }
17653
17654
17655
17656
17657
17658
17659
17660 Lisp_Object
17661 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17662 {
17663 Lisp_Object val;
17664
17665 if (ASCII_CHAR_P (c))
17666 {
17667 val = dp->ascii;
17668 if (SUB_CHAR_TABLE_P (val))
17669 val = XSUB_CHAR_TABLE (val)->contents[c];
17670 }
17671 else
17672 {
17673 Lisp_Object table;
17674
17675 XSETCHAR_TABLE (table, dp);
17676 val = char_table_ref (table, c);
17677 }
17678 if (NILP (val))
17679 val = dp->defalt;
17680 return val;
17681 }
17682
17683 static int buffer_flip_blocked_depth;
17684
17685 static void
17686 block_buffer_flips (void)
17687 {
17688 eassert (buffer_flip_blocked_depth >= 0);
17689 buffer_flip_blocked_depth++;
17690 }
17691
17692 static void
17693 unblock_buffer_flips (void)
17694 {
17695 eassert (buffer_flip_blocked_depth > 0);
17696 if (--buffer_flip_blocked_depth == 0)
17697 {
17698 Lisp_Object tail, frame;
17699 block_input ();
17700 FOR_EACH_FRAME (tail, frame)
17701 {
17702 struct frame *f = XFRAME (frame);
17703 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17704 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17705 }
17706 unblock_input ();
17707 }
17708 }
17709
17710 bool
17711 buffer_flipping_blocked_p (void)
17712 {
17713 return buffer_flip_blocked_depth > 0;
17714 }
17715
17716
17717
17718
17719
17720
17721
17722
17723 static void
17724 redisplay_windows (Lisp_Object window)
17725 {
17726 while (!NILP (window))
17727 {
17728 struct window *w = XWINDOW (window);
17729
17730 if (WINDOWP (w->contents))
17731 redisplay_windows (w->contents);
17732 else if (BUFFERP (w->contents))
17733 {
17734 displayed_buffer = XBUFFER (w->contents);
17735
17736
17737 internal_condition_case_1 (redisplay_window_0, window,
17738 list_of_error,
17739 redisplay_window_error);
17740 }
17741
17742 window = w->next;
17743 }
17744 }
17745
17746 static Lisp_Object
17747 redisplay_window_error (Lisp_Object error_data)
17748 {
17749 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17750
17751
17752
17753 if (max_redisplay_ticks > 0
17754 && CONSP (error_data)
17755 && EQ (XCAR (error_data), Qerror)
17756 && STRINGP (XCAR (XCDR (error_data))))
17757 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17758 XCAR (XCDR (error_data))),
17759 Vdelayed_warnings_list);
17760 return Qnil;
17761 }
17762
17763 static Lisp_Object
17764 redisplay_window_0 (Lisp_Object window)
17765 {
17766 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17767 redisplay_window (window, false);
17768 return Qnil;
17769 }
17770
17771 static Lisp_Object
17772 redisplay_window_1 (Lisp_Object window)
17773 {
17774 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17775 redisplay_window (window, true);
17776 return Qnil;
17777 }
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789
17790
17791
17792
17793
17794
17795
17796
17797 void
17798 update_redisplay_ticks (int ticks, struct window *w)
17799 {
17800
17801 static struct window *cwindow;
17802 static EMACS_INT window_ticks;
17803
17804
17805
17806
17807 if (!ticks && w != cwindow)
17808 {
17809 cwindow = w;
17810 window_ticks = 0;
17811 }
17812
17813
17814 if ((!w && !redisplaying_p && !display_working_on_window_p)
17815
17816
17817 || (w && MINI_WINDOW_P (w)))
17818 return;
17819
17820 if (ticks > 0)
17821 window_ticks += ticks;
17822 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17823 {
17824
17825
17826
17827 Lisp_Object contents = w ? w->contents : Qnil;
17828 char *bufname =
17829 NILP (contents)
17830 ? SSDATA (BVAR (current_buffer, name))
17831 : (BUFFERP (contents)
17832 ? SSDATA (BVAR (XBUFFER (contents), name))
17833 : (char *) "<unknown>");
17834
17835 windows_or_buffers_changed = 177;
17836
17837
17838
17839 if (w && w->desired_matrix)
17840 w->desired_matrix->no_scrolling_p = true;
17841 error ("Window showing buffer %s takes too long to redisplay", bufname);
17842 }
17843 }
17844
17845
17846
17847
17848
17849
17850
17851
17852
17853
17854 static bool
17855 set_cursor_from_row (struct window *w, struct glyph_row *row,
17856 struct glyph_matrix *matrix,
17857 ptrdiff_t delta, ptrdiff_t delta_bytes,
17858 int dy, int dvpos)
17859 {
17860 struct glyph *glyph = row->glyphs[TEXT_AREA];
17861 struct glyph *end = glyph + row->used[TEXT_AREA];
17862 struct glyph *cursor = NULL;
17863
17864 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17865 int x = row->x;
17866 ptrdiff_t pt_old = PT - delta;
17867 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17868 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17869 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17870
17871
17872 struct glyph *glyphs_end = end;
17873
17874
17875 bool match_with_avoid_cursor = false;
17876
17877
17878 bool string_seen = false;
17879
17880
17881 ptrdiff_t bpos_max = pos_before;
17882 ptrdiff_t bpos_min = pos_after;
17883
17884
17885 ptrdiff_t bpos_covered = 0;
17886
17887
17888 bool string_from_text_prop = false;
17889
17890
17891
17892
17893 eassert (!row->mode_line_p);
17894 if (row->mode_line_p)
17895 return false;
17896
17897
17898
17899
17900 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17901 {
17902 if (!row->reversed_p)
17903 {
17904 while (glyph < end
17905 && NILP (glyph->object)
17906 && glyph->charpos < 0)
17907 {
17908 x += glyph->pixel_width;
17909 ++glyph;
17910 }
17911 while (end > glyph
17912 && NILP ((end - 1)->object)
17913
17914
17915 && (end - 1)->charpos <= 0)
17916 --end;
17917 glyph_before = glyph - 1;
17918 glyph_after = end;
17919 }
17920 else
17921 {
17922 struct glyph *g;
17923
17924
17925
17926 glyphs_end = end = glyph - 1;
17927 glyph += row->used[TEXT_AREA] - 1;
17928
17929 while (glyph > end + 1
17930 && NILP (glyph->object)
17931 && glyph->charpos < 0)
17932 --glyph;
17933 if (NILP (glyph->object) && glyph->charpos < 0)
17934 --glyph;
17935
17936
17937 for (x = 0, g = end + 1; g < glyph; g++)
17938 x += g->pixel_width;
17939 while (end < glyph
17940 && NILP ((end + 1)->object)
17941 && (end + 1)->charpos <= 0)
17942 ++end;
17943 glyph_before = glyph + 1;
17944 glyph_after = end;
17945 }
17946 }
17947 else if (row->reversed_p)
17948 {
17949
17950
17951
17952 cursor = end - 1;
17953
17954
17955
17956 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17957 && !WINDOW_RIGHTMOST_P (w)
17958 && cursor == row->glyphs[LAST_AREA] - 1)
17959 cursor--;
17960 x = -1;
17961 }
17962
17963
17964
17965
17966
17967 if (!row->reversed_p)
17968 while (
17969 glyph < end
17970
17971 && !NILP (glyph->object))
17972 {
17973 if (BUFFERP (glyph->object))
17974 {
17975 ptrdiff_t dpos = glyph->charpos - pt_old;
17976
17977 if (glyph->charpos > bpos_max)
17978 bpos_max = glyph->charpos;
17979 if (glyph->charpos < bpos_min)
17980 bpos_min = glyph->charpos;
17981 if (!glyph->avoid_cursor_p)
17982 {
17983
17984
17985 if (dpos == 0)
17986 {
17987 match_with_avoid_cursor = false;
17988 break;
17989 }
17990
17991
17992 if (0 > dpos && dpos > pos_before - pt_old)
17993 {
17994 pos_before = glyph->charpos;
17995 glyph_before = glyph;
17996 }
17997 else if (0 < dpos && dpos < pos_after - pt_old)
17998 {
17999 pos_after = glyph->charpos;
18000 glyph_after = glyph;
18001 }
18002 }
18003 else if (dpos == 0)
18004 match_with_avoid_cursor = true;
18005 }
18006 else if (STRINGP (glyph->object))
18007 {
18008 Lisp_Object chprop;
18009 ptrdiff_t glyph_pos = glyph->charpos;
18010
18011 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18012 glyph->object);
18013 if (!NILP (chprop))
18014 {
18015
18016
18017
18018
18019
18020
18021
18022
18023
18024
18025 ptrdiff_t prop_pos =
18026 string_buffer_position_lim (glyph->object, pos_before,
18027 pos_after, false);
18028
18029 if (prop_pos >= pos_before)
18030 bpos_max = prop_pos;
18031 }
18032 if (FIXNUMP (chprop))
18033 {
18034 bpos_covered = bpos_max + XFIXNUM (chprop);
18035
18036
18037
18038
18039
18040
18041
18042
18043
18044
18045
18046 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18047 {
18048 cursor = glyph;
18049 break;
18050 }
18051 }
18052
18053 string_seen = true;
18054 }
18055 x += glyph->pixel_width;
18056 ++glyph;
18057 }
18058 else if (glyph > end)
18059 while (!NILP (glyph->object))
18060 {
18061 if (BUFFERP (glyph->object))
18062 {
18063 ptrdiff_t dpos = glyph->charpos - pt_old;
18064
18065 if (glyph->charpos > bpos_max)
18066 bpos_max = glyph->charpos;
18067 if (glyph->charpos < bpos_min)
18068 bpos_min = glyph->charpos;
18069 if (!glyph->avoid_cursor_p)
18070 {
18071 if (dpos == 0)
18072 {
18073 match_with_avoid_cursor = false;
18074 break;
18075 }
18076 if (0 > dpos && dpos > pos_before - pt_old)
18077 {
18078 pos_before = glyph->charpos;
18079 glyph_before = glyph;
18080 }
18081 else if (0 < dpos && dpos < pos_after - pt_old)
18082 {
18083 pos_after = glyph->charpos;
18084 glyph_after = glyph;
18085 }
18086 }
18087 else if (dpos == 0)
18088 match_with_avoid_cursor = true;
18089 }
18090 else if (STRINGP (glyph->object))
18091 {
18092 Lisp_Object chprop;
18093 ptrdiff_t glyph_pos = glyph->charpos;
18094
18095 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18096 glyph->object);
18097 if (!NILP (chprop))
18098 {
18099 ptrdiff_t prop_pos =
18100 string_buffer_position_lim (glyph->object, pos_before,
18101 pos_after, false);
18102
18103 if (prop_pos >= pos_before)
18104 bpos_max = prop_pos;
18105 }
18106 if (FIXNUMP (chprop))
18107 {
18108 bpos_covered = bpos_max + XFIXNUM (chprop);
18109
18110
18111
18112 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18113 {
18114 cursor = glyph;
18115 break;
18116 }
18117 }
18118 string_seen = true;
18119 }
18120 --glyph;
18121 if (glyph == glyphs_end)
18122 {
18123 x--;
18124 break;
18125 }
18126 x -= glyph->pixel_width;
18127 }
18128
18129
18130
18131
18132 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18133 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
18134 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
18135 {
18136
18137
18138
18139
18140
18141 bool empty_line_p =
18142 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18143 && NILP (glyph->object) && glyph->charpos > 0
18144
18145
18146
18147
18148 && !(row->continued_p || row->truncated_on_right_p));
18149
18150 if (row->ends_in_ellipsis_p && pos_after == last_pos)
18151 {
18152 ptrdiff_t ellipsis_pos;
18153
18154
18155 if (!row->reversed_p)
18156 {
18157 ellipsis_pos = (glyph - 1)->charpos;
18158 while (glyph > row->glyphs[TEXT_AREA]
18159 && (glyph - 1)->charpos == ellipsis_pos)
18160 glyph--, x -= glyph->pixel_width;
18161
18162
18163
18164 x += glyph->pixel_width;
18165 glyph++;
18166 }
18167 else
18168 {
18169 ellipsis_pos = (glyph + 1)->charpos;
18170 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18171 && (glyph + 1)->charpos == ellipsis_pos)
18172 glyph++, x += glyph->pixel_width;
18173 x -= glyph->pixel_width;
18174 glyph--;
18175 }
18176 }
18177 else if (match_with_avoid_cursor)
18178 {
18179 cursor = glyph_after;
18180 x = -1;
18181 }
18182 else if (string_seen)
18183 {
18184 int incr = row->reversed_p ? -1 : +1;
18185
18186
18187
18188
18189
18190
18191 struct glyph *start, *stop;
18192 ptrdiff_t pos = pos_before;
18193
18194 x = -1;
18195
18196
18197
18198
18199
18200
18201 if (row->ends_in_newline_from_string_p)
18202 {
18203 glyph_after = end;
18204 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18205 }
18206
18207
18208
18209
18210
18211
18212
18213
18214
18215 if (!row->reversed_p)
18216 {
18217 start = min (glyph_before, glyph_after);
18218 stop = max (glyph_before, glyph_after);
18219 }
18220 else
18221 {
18222 start = max (glyph_before, glyph_after);
18223 stop = min (glyph_before, glyph_after);
18224 }
18225 for (glyph = start + incr;
18226 row->reversed_p ? glyph > stop : glyph < stop; )
18227 {
18228
18229
18230
18231
18232 if (STRINGP (glyph->object))
18233 {
18234 Lisp_Object str;
18235 ptrdiff_t tem;
18236
18237
18238 ptrdiff_t lim = pos_after
18239 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18240
18241 string_from_text_prop = false;
18242 str = glyph->object;
18243 tem = string_buffer_position_lim (str, pos, lim, false);
18244 if (tem == 0
18245 || pos <= tem)
18246 {
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256
18257 if (tem == 0
18258 || tem == pt_old
18259 || (tem - pt_old > 0 && tem < pos_after))
18260 {
18261
18262
18263
18264
18265
18266
18267 ptrdiff_t strpos = glyph->charpos;
18268
18269 if (tem)
18270 {
18271 cursor = glyph;
18272 string_from_text_prop = true;
18273 }
18274 for ( ;
18275 (row->reversed_p ? glyph > stop : glyph < stop)
18276 && EQ (glyph->object, str);
18277 glyph += incr)
18278 {
18279 Lisp_Object cprop;
18280 ptrdiff_t gpos = glyph->charpos;
18281
18282 cprop = Fget_char_property (make_fixnum (gpos),
18283 Qcursor,
18284 glyph->object);
18285 if (!NILP (cprop))
18286 {
18287 cursor = glyph;
18288 break;
18289 }
18290 if (tem && glyph->charpos < strpos)
18291 {
18292 strpos = glyph->charpos;
18293 cursor = glyph;
18294 }
18295 }
18296
18297 if (tem == pt_old
18298 || (tem - pt_old > 0 && tem < pos_after))
18299 goto compute_x;
18300 }
18301 if (tem)
18302 pos = tem + 1;
18303 }
18304
18305
18306 while ((row->reversed_p ? glyph > stop : glyph < stop)
18307 && EQ (glyph->object, str))
18308 glyph += incr;
18309 }
18310 else
18311 glyph += incr;
18312 }
18313
18314
18315
18316 if (cursor == NULL
18317 && (row->reversed_p ? glyph <= end : glyph >= end)
18318 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18319 && STRINGP (end->object)
18320 && row->continued_p)
18321 return false;
18322 }
18323
18324
18325
18326
18327
18328 else if (row->truncated_on_left_p && pt_old < bpos_min)
18329 {
18330 cursor = glyph_before;
18331 x = -1;
18332 }
18333 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18334
18335 || (!empty_line_p
18336 && (row->reversed_p
18337 ? glyph_after > glyphs_end
18338 : glyph_after < glyphs_end)))
18339 {
18340 cursor = glyph_after;
18341 x = -1;
18342 }
18343 }
18344
18345 compute_x:
18346 if (cursor != NULL)
18347 glyph = cursor;
18348 else if (glyph == glyphs_end
18349 && pos_before == pos_after
18350 && STRINGP ((row->reversed_p
18351 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18352 : row->glyphs[TEXT_AREA])->object))
18353 {
18354
18355
18356
18357
18358 glyph =
18359 row->reversed_p
18360 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18361 : row->glyphs[TEXT_AREA];
18362 }
18363 if (x < 0)
18364 {
18365 struct glyph *g;
18366
18367
18368 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18369 {
18370 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18371 emacs_abort ();
18372 x += g->pixel_width;
18373 }
18374 }
18375
18376
18377
18378
18379
18380
18381 if (
18382 w->cursor.vpos >= 0
18383
18384 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18385
18386
18387
18388
18389
18390 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18391 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18392 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18393 {
18394 struct glyph *g1
18395 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18396
18397
18398 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18399 return false;
18400
18401
18402 if (
18403 w->cursor.hpos >= 0
18404 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18405 && ((BUFFERP (g1->object)
18406 && (g1->charpos == pt_old
18407 || (BUFFERP (glyph->object)
18408 && eabs (g1->charpos - pt_old)
18409 < eabs (glyph->charpos - pt_old))))
18410
18411
18412 || (STRINGP (g1->object)
18413 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18414 Qcursor, g1->object))
18415
18416
18417
18418 || (EQ (g1->object, glyph->object)
18419 && string_from_text_prop)
18420
18421
18422 || (NILP (glyph->object)
18423 && glyph->charpos != pt_old)))))
18424 return false;
18425
18426 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18427
18428
18429
18430 || (!row->continued_p
18431 && NILP (glyph->object)
18432 && glyph->charpos == 0
18433 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18434
18435
18436
18437
18438
18439 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18440 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18441 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18442 return false;
18443 }
18444 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18445 w->cursor.x = x;
18446 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18447 w->cursor.y = row->y + dy;
18448
18449 if (w == XWINDOW (selected_window))
18450 {
18451 if (!row->continued_p
18452 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18453 && row->x == 0)
18454 {
18455 this_line_buffer = XBUFFER (w->contents);
18456
18457 CHARPOS (this_line_start_pos)
18458 = MATRIX_ROW_START_CHARPOS (row) + delta;
18459 BYTEPOS (this_line_start_pos)
18460 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18461
18462 CHARPOS (this_line_end_pos)
18463 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18464 BYTEPOS (this_line_end_pos)
18465 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18466
18467 this_line_y = w->cursor.y;
18468 this_line_pixel_height = row->height;
18469 this_line_vpos = w->cursor.vpos;
18470 this_line_start_x = row->x;
18471 }
18472 else
18473 CHARPOS (this_line_start_pos) = 0;
18474 }
18475
18476 return true;
18477 }
18478
18479
18480
18481
18482
18483
18484
18485 static struct text_pos
18486 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18487 {
18488 struct window *w = XWINDOW (window);
18489 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18490
18491 eassert (current_buffer == XBUFFER (w->contents));
18492
18493 if (!NILP (Vwindow_scroll_functions))
18494 {
18495 specpdl_ref count = SPECPDL_INDEX ();
18496 specbind (Qinhibit_quit, Qt);
18497 safe_run_hooks_2
18498 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18499 unbind_to (count, Qnil);
18500 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18501
18502 set_buffer_internal (XBUFFER (w->contents));
18503 }
18504
18505 return startp;
18506 }
18507
18508
18509
18510
18511
18512
18513
18514
18515
18516
18517
18518
18519
18520
18521
18522
18523
18524
18525
18526
18527
18528
18529 static bool
18530 cursor_row_fully_visible_p (struct window *w, bool force_p,
18531 bool current_matrix_p,
18532 bool just_test_user_preference_p)
18533 {
18534 struct glyph_matrix *matrix;
18535 struct glyph_row *row;
18536 int window_height;
18537 Lisp_Object mclfv_p =
18538 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18539
18540
18541 if (BASE_EQ (mclfv_p, Qunbound))
18542 mclfv_p = Vmake_cursor_line_fully_visible;
18543
18544
18545 if (FUNCTIONP (mclfv_p))
18546 {
18547 Lisp_Object window;
18548 XSETWINDOW (window, w);
18549
18550
18551 Lisp_Object val = safe_call1 (mclfv_p, window);
18552 if (NILP (val))
18553 return true;
18554 else if (just_test_user_preference_p)
18555 return false;
18556 }
18557 else if (NILP (mclfv_p))
18558 return true;
18559 else if (just_test_user_preference_p)
18560 return false;
18561
18562
18563
18564 if (w->cursor.vpos < 0)
18565 return true;
18566
18567 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18568 row = MATRIX_ROW (matrix, w->cursor.vpos);
18569
18570
18571 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18572 return true;
18573
18574
18575
18576 window_height = window_box_height (w);
18577 if (row->height >= window_height)
18578 {
18579 if (!force_p || MINI_WINDOW_P (w)
18580 || w->vscroll || w->cursor.vpos == 0)
18581 return true;
18582 }
18583 return false;
18584 }
18585
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596
18597
18598
18599
18600
18601
18602
18603
18604
18605 enum
18606 {
18607 SCROLLING_SUCCESS = 1,
18608 SCROLLING_FAILED = 0,
18609 SCROLLING_NEED_LARGER_MATRICES = -1
18610 };
18611
18612
18613
18614
18615
18616 #define SCROLL_LIMIT 100
18617
18618 static int
18619 try_scrolling (Lisp_Object window, bool just_this_one_p,
18620 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18621 bool temp_scroll_step, bool last_line_misfit)
18622 {
18623 struct window *w = XWINDOW (window);
18624 struct text_pos pos, startp;
18625 struct it it;
18626 int this_scroll_margin, scroll_max, rc, height;
18627 int dy = 0, amount_to_scroll = 0;
18628 bool scroll_down_p = false;
18629 int extra_scroll_margin_lines = last_line_misfit;
18630 Lisp_Object aggressive;
18631
18632 int scroll_limit = SCROLL_LIMIT;
18633 int frame_line_height = default_line_pixel_height (w);
18634
18635 #ifdef GLYPH_DEBUG
18636 debug_method_add (w, "try_scrolling");
18637 #endif
18638
18639 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18640
18641 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18642
18643
18644
18645
18646
18647 if (arg_scroll_conservatively > scroll_limit)
18648 {
18649 arg_scroll_conservatively = scroll_limit + 1;
18650 scroll_max = scroll_limit * frame_line_height;
18651 }
18652 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18653
18654
18655 {
18656 intmax_t scroll_lines_max
18657 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18658 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18659 scroll_max = scroll_lines * frame_line_height;
18660 }
18661 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18662 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18663
18664
18665 scroll_max = 10 * frame_line_height;
18666 else
18667 scroll_max = 0;
18668
18669 too_near_end:
18670
18671
18672 if (PT > CHARPOS (startp))
18673 {
18674 int scroll_margin_y;
18675
18676
18677
18678 start_display (&it, w, startp);
18679 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18680 - this_scroll_margin
18681 - frame_line_height * extra_scroll_margin_lines;
18682 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18683 (MOVE_TO_POS | MOVE_TO_Y));
18684
18685 if (PT > CHARPOS (it.current.pos))
18686 {
18687 int y0 = line_bottom_y (&it);
18688
18689
18690
18691
18692
18693 int slack = max (scroll_max, 10 * frame_line_height);
18694 int y_to_move = it.last_visible_y + slack;
18695
18696
18697
18698
18699
18700 move_it_to (&it, PT, -1, y_to_move,
18701 -1, MOVE_TO_POS | MOVE_TO_Y);
18702 dy = line_bottom_y (&it) - y0;
18703
18704 if (dy > scroll_max)
18705 return SCROLLING_FAILED;
18706
18707 if (dy > 0)
18708 scroll_down_p = true;
18709 }
18710 else if (PT == IT_CHARPOS (it)
18711 && IT_CHARPOS (it) < ZV
18712 && it.method == GET_FROM_STRING
18713 && arg_scroll_conservatively > scroll_limit
18714 && it.current_x == 0)
18715 {
18716 enum move_it_result skip;
18717 int y1 = it.current_y;
18718 int vpos;
18719
18720
18721
18722
18723
18724
18725
18726 do {
18727 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18728 if (skip != MOVE_NEWLINE_OR_CR
18729 || IT_CHARPOS (it) != PT
18730 || it.method == GET_FROM_BUFFER)
18731 break;
18732 vpos = it.vpos;
18733 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18734 } while (it.vpos > vpos);
18735
18736 dy = it.current_y - y1;
18737
18738 if (dy > scroll_max)
18739 return SCROLLING_FAILED;
18740
18741 if (dy > 0)
18742 scroll_down_p = true;
18743 }
18744 }
18745
18746 if (scroll_down_p)
18747 {
18748
18749
18750
18751
18752 if (arg_scroll_conservatively)
18753 amount_to_scroll
18754 = min (max (dy, frame_line_height),
18755 frame_line_height * arg_scroll_conservatively);
18756 else if (scroll_step || temp_scroll_step)
18757 amount_to_scroll = scroll_max;
18758 else
18759 {
18760 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18761 height = WINDOW_BOX_TEXT_HEIGHT (w);
18762 if (NUMBERP (aggressive))
18763 {
18764 double float_amount = XFLOATINT (aggressive) * height;
18765 int aggressive_scroll = float_amount;
18766 if (aggressive_scroll == 0 && float_amount > 0)
18767 aggressive_scroll = 1;
18768
18769
18770
18771
18772
18773
18774 if (aggressive_scroll + 2 * this_scroll_margin > height)
18775 aggressive_scroll = height - 2 * this_scroll_margin;
18776 amount_to_scroll = dy + aggressive_scroll;
18777 }
18778 }
18779
18780 if (amount_to_scroll <= 0)
18781 return SCROLLING_FAILED;
18782
18783 start_display (&it, w, startp);
18784 if (arg_scroll_conservatively <= scroll_limit)
18785 move_it_vertically (&it, amount_to_scroll);
18786 else
18787 {
18788
18789
18790
18791
18792
18793
18794 struct it it1;
18795 void *it1data = NULL;
18796
18797
18798 int start_y;
18799
18800 SAVE_IT (it1, it, it1data);
18801 start_y = line_bottom_y (&it1);
18802 do {
18803 RESTORE_IT (&it, &it, it1data);
18804 move_it_by_lines (&it, 1);
18805 SAVE_IT (it1, it, it1data);
18806 } while (IT_CHARPOS (it) < ZV
18807 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18808 bidi_unshelve_cache (it1data, true);
18809 }
18810
18811
18812 if (IT_CHARPOS (it) == CHARPOS (startp))
18813 move_it_by_lines (&it, 1);
18814 startp = it.current.pos;
18815 }
18816 else
18817 {
18818 struct text_pos scroll_margin_pos = startp;
18819 int y_offset = 0;
18820
18821
18822
18823 if (this_scroll_margin)
18824 {
18825 int y_start;
18826
18827 start_display (&it, w, startp);
18828 y_start = it.current_y;
18829 move_it_vertically (&it, this_scroll_margin);
18830 scroll_margin_pos = it.current.pos;
18831
18832
18833
18834 if (IT_CHARPOS (it) == ZV
18835 && it.current_y - y_start < this_scroll_margin)
18836 y_offset = this_scroll_margin - (it.current_y - y_start);
18837 }
18838
18839 if (PT < CHARPOS (scroll_margin_pos))
18840 {
18841
18842
18843 int y0, y_to_move;
18844
18845
18846
18847
18848
18849
18850 SET_TEXT_POS (pos, PT, PT_BYTE);
18851 start_display (&it, w, pos);
18852 y0 = it.current_y;
18853 y_to_move = max (it.last_visible_y,
18854 max (scroll_max, 10 * frame_line_height));
18855 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18856 y_to_move, -1,
18857 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18858 dy = it.current_y - y0;
18859 if (dy > scroll_max
18860 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18861 return SCROLLING_FAILED;
18862
18863
18864 dy += y_offset;
18865
18866
18867 start_display (&it, w, startp);
18868
18869 if (arg_scroll_conservatively)
18870 amount_to_scroll
18871 = min (max (dy, frame_line_height),
18872 frame_line_height * arg_scroll_conservatively);
18873 else if (scroll_step || temp_scroll_step)
18874 amount_to_scroll = scroll_max;
18875 else
18876 {
18877 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18878 height = WINDOW_BOX_TEXT_HEIGHT (w);
18879 if (NUMBERP (aggressive))
18880 {
18881 double float_amount = XFLOATINT (aggressive) * height;
18882 int aggressive_scroll = float_amount;
18883 if (aggressive_scroll == 0 && float_amount > 0)
18884 aggressive_scroll = 1;
18885
18886
18887
18888
18889 if (aggressive_scroll + 2 * this_scroll_margin > height)
18890 aggressive_scroll = height - 2 * this_scroll_margin;
18891 amount_to_scroll = dy + aggressive_scroll;
18892 }
18893 }
18894
18895 if (amount_to_scroll <= 0)
18896 return SCROLLING_FAILED;
18897
18898 move_it_vertically_backward (&it, amount_to_scroll);
18899 startp = it.current.pos;
18900 }
18901 }
18902
18903
18904 startp = run_window_scroll_functions (window, startp);
18905
18906
18907
18908 if (!try_window (window, startp, 0))
18909 rc = SCROLLING_NEED_LARGER_MATRICES;
18910 else if (w->cursor.vpos < 0)
18911 {
18912 clear_glyph_matrix (w->desired_matrix);
18913 rc = SCROLLING_FAILED;
18914 }
18915 else
18916 {
18917
18918 if (!just_this_one_p
18919 || current_buffer->clip_changed
18920 || BEG_UNCHANGED < CHARPOS (startp))
18921 w->base_line_number = 0;
18922
18923
18924
18925 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18926 false, false)
18927
18928
18929
18930 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18931 {
18932 clear_glyph_matrix (w->desired_matrix);
18933 ++extra_scroll_margin_lines;
18934 goto too_near_end;
18935 }
18936 rc = SCROLLING_SUCCESS;
18937 }
18938
18939 return rc;
18940 }
18941
18942
18943
18944
18945
18946
18947
18948
18949
18950
18951
18952
18953 static bool
18954 compute_window_start_on_continuation_line (struct window *w)
18955 {
18956 struct text_pos pos, start_pos, pos_before_pt;
18957 bool window_start_changed_p = false;
18958
18959 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18960
18961
18962
18963
18964 if (CHARPOS (start_pos) > BEGV
18965 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
18966 {
18967 struct it it;
18968 struct glyph_row *row;
18969
18970
18971 if (CHARPOS (start_pos) < BEGV)
18972 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
18973 else if (CHARPOS (start_pos) > ZV)
18974 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
18975
18976
18977
18978 row = w->desired_matrix->rows + window_wants_tab_line (w)
18979 + window_wants_header_line (w);
18980 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
18981 row, DEFAULT_FACE_ID);
18982 reseat_at_previous_visible_line_start (&it);
18983
18984
18985
18986
18987
18988
18989
18990 if (IT_CHARPOS (it) <= PT
18991 && (CHARPOS (start_pos) - IT_CHARPOS (it)
18992
18993 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
18994 {
18995 int min_distance, distance;
18996
18997
18998
18999
19000
19001
19002
19003 pos_before_pt = pos = it.current.pos;
19004 min_distance = DISP_INFINITY;
19005 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
19006 distance < min_distance)
19007 {
19008 min_distance = distance;
19009 if (CHARPOS (pos) <= PT)
19010 pos_before_pt = pos;
19011 pos = it.current.pos;
19012 if (it.line_wrap == WORD_WRAP)
19013 {
19014
19015
19016
19017
19018
19019
19020
19021
19022
19023 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
19024 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19025 move_it_to (&it, ZV, 0,
19026 it.current_y + it.max_ascent + it.max_descent, -1,
19027 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19028 }
19029 else
19030 move_it_by_lines (&it, 1);
19031 }
19032
19033
19034
19035
19036
19037 if (CHARPOS (pos) > PT)
19038 pos = pos_before_pt;
19039
19040
19041 SET_MARKER_FROM_TEXT_POS (w->start, pos);
19042 window_start_changed_p = true;
19043 }
19044 }
19045
19046 return window_start_changed_p;
19047 }
19048
19049
19050
19051
19052
19053
19054
19055
19056
19057
19058
19059
19060
19061
19062
19063
19064
19065 enum
19066 {
19067 CURSOR_MOVEMENT_SUCCESS,
19068 CURSOR_MOVEMENT_CANNOT_BE_USED,
19069 CURSOR_MOVEMENT_MUST_SCROLL,
19070 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
19071 };
19072
19073 static int
19074 try_cursor_movement (Lisp_Object window, struct text_pos startp,
19075 bool *scroll_step)
19076 {
19077 struct window *w = XWINDOW (window);
19078 struct frame *f = XFRAME (w->frame);
19079 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
19080
19081 #ifdef GLYPH_DEBUG
19082 if (inhibit_try_cursor_movement)
19083 return rc;
19084 #endif
19085
19086
19087
19088
19089 eassert (w->last_point > 0);
19090
19091
19092
19093 eassert (!w->window_end_valid
19094 || w->window_end_vpos < w->current_matrix->nrows);
19095
19096
19097
19098 if (
19099 PT >= CHARPOS (startp)
19100
19101 && !current_buffer->clip_changed
19102
19103
19104
19105
19106 && !update_mode_lines
19107 && !windows_or_buffers_changed
19108 && !f->cursor_type_changed
19109 && NILP (Vshow_trailing_whitespace)
19110
19111
19112 && !EQ (Vdisplay_line_numbers, Qrelative)
19113 && !EQ (Vdisplay_line_numbers, Qvisual)
19114
19115
19116
19117 && !(!NILP (Vdisplay_line_numbers)
19118 && NILP (Finternal_lisp_face_equal_p (Qline_number,
19119 Qline_number_current_line,
19120 w->frame)))
19121
19122
19123
19124
19125
19126
19127 && !EQ (window, minibuf_window)
19128
19129
19130
19131 && !overlay_arrow_in_current_buffer_p ())
19132 {
19133 int this_scroll_margin, top_scroll_margin;
19134 struct glyph_row *row = NULL;
19135
19136 #ifdef GLYPH_DEBUG
19137 debug_method_add (w, "cursor movement");
19138 #endif
19139
19140 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
19141
19142 top_scroll_margin = this_scroll_margin;
19143 if (window_wants_tab_line (w))
19144 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
19145 if (window_wants_header_line (w))
19146 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
19147
19148
19149
19150 if (w->last_cursor_vpos < 0
19151 || w->last_cursor_vpos >= w->current_matrix->nrows)
19152 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19153 else
19154 {
19155 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
19156
19157 if (row->tab_line_p)
19158 ++row;
19159 if (row->mode_line_p)
19160 ++row;
19161 if (!row->enabled_p)
19162 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19163 }
19164
19165 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
19166 {
19167 bool scroll_p = false, must_scroll = false;
19168 int last_y = window_text_bottom_y (w) - this_scroll_margin;
19169
19170 if (PT > w->last_point)
19171 {
19172
19173 while (MATRIX_ROW_END_CHARPOS (row) < PT
19174 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19175 {
19176 eassert (row->enabled_p);
19177 ++row;
19178 }
19179
19180
19181
19182
19183 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19184 && MATRIX_ROW_END_CHARPOS (row) == PT
19185 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19186 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19187 && !cursor_row_p (row))
19188 ++row;
19189
19190
19191
19192
19193
19194 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19195 || PT > MATRIX_ROW_END_CHARPOS (row)
19196
19197
19198 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19199 && PT == MATRIX_ROW_END_CHARPOS (row)
19200 && !row->ends_at_zv_p
19201 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19202 scroll_p = true;
19203 }
19204 else if (PT < w->last_point)
19205 {
19206
19207
19208 struct glyph_row *row0 = row;
19209
19210 while (!row->mode_line_p
19211 && (MATRIX_ROW_START_CHARPOS (row) > PT
19212 || (MATRIX_ROW_START_CHARPOS (row) == PT
19213 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19214 || (
19215 row > w->current_matrix->rows
19216 && (row-1)->ends_in_newline_from_string_p))))
19217 && (row->y > top_scroll_margin
19218 || CHARPOS (startp) == BEGV))
19219 {
19220 eassert (row->enabled_p);
19221 --row;
19222 }
19223
19224
19225
19226
19227
19228 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19229 && PT <= MATRIX_ROW_END_CHARPOS (row))
19230 && row0->continued_p)
19231 {
19232 row = row0;
19233 while (MATRIX_ROW_START_CHARPOS (row) > PT
19234 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19235 {
19236 eassert (row->enabled_p);
19237 ++row;
19238 }
19239 }
19240
19241
19242
19243
19244
19245
19246 if (row < w->current_matrix->rows
19247 || row->mode_line_p)
19248 {
19249 row = w->current_matrix->rows;
19250
19251 if (row->tab_line_p)
19252 ++row;
19253 if (row->mode_line_p)
19254 ++row;
19255 }
19256
19257
19258
19259 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19260 && MATRIX_ROW_END_CHARPOS (row) == PT
19261 && !cursor_row_p (row))
19262 ++row;
19263
19264
19265
19266 if ((row->y < top_scroll_margin
19267 && CHARPOS (startp) != BEGV)
19268 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19269 || PT > MATRIX_ROW_END_CHARPOS (row)
19270 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19271 && PT == MATRIX_ROW_END_CHARPOS (row)
19272 && !row->ends_at_zv_p
19273 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19274 scroll_p = true;
19275 }
19276 else
19277 {
19278
19279
19280 rc = CURSOR_MOVEMENT_SUCCESS;
19281 }
19282
19283 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19284 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19285
19286
19287 || (MATRIX_ROW_END_CHARPOS (row-1)
19288 == MATRIX_ROW_START_CHARPOS (row))))
19289 || PT > MATRIX_ROW_END_CHARPOS (row))
19290 {
19291
19292 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19293 must_scroll = true;
19294 }
19295 else if (rc != CURSOR_MOVEMENT_SUCCESS
19296 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19297 {
19298 struct glyph_row *row1;
19299
19300
19301
19302
19303
19304
19305
19306
19307
19308
19309
19310 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19311 MATRIX_ROW_CONTINUATION_LINE_P (row);
19312 --row)
19313 {
19314
19315
19316
19317 if (row <= row1)
19318 {
19319 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19320 break;
19321 }
19322 eassert (row->enabled_p);
19323 }
19324 }
19325 if (must_scroll)
19326 ;
19327 else if (rc != CURSOR_MOVEMENT_SUCCESS
19328 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19329
19330
19331
19332 && !row->mode_line_p
19333 && !cursor_row_fully_visible_p (w, true, true, true))
19334 {
19335 if (PT == MATRIX_ROW_END_CHARPOS (row)
19336 && !row->ends_at_zv_p
19337 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19338 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19339 else if (row->height > window_box_height (w))
19340 {
19341
19342
19343
19344
19345 *scroll_step = true;
19346 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19347 }
19348 else
19349 {
19350 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19351 if (!cursor_row_fully_visible_p (w, false, true, false))
19352 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19353 else
19354 rc = CURSOR_MOVEMENT_SUCCESS;
19355 }
19356 }
19357 else if (scroll_p)
19358 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19359 else if (rc != CURSOR_MOVEMENT_SUCCESS
19360 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19361 {
19362
19363
19364
19365
19366
19367
19368
19369 bool rv = false;
19370 bool pt_invis = false;
19371 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19372 Qinvisible,
19373 Qnil, NULL);
19374
19375 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19376 pt_invis = true;
19377
19378 do
19379 {
19380 bool at_zv_p = false, exact_match_p = false;
19381
19382
19383
19384
19385
19386 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19387 && PT <= MATRIX_ROW_END_CHARPOS (row)
19388 && cursor_row_p (row))
19389 rv |= set_cursor_from_row (w, row, w->current_matrix,
19390 0, 0, 0, 0);
19391
19392
19393
19394 if (rv)
19395 {
19396 at_zv_p = MATRIX_ROW (w->current_matrix,
19397 w->cursor.vpos)->ends_at_zv_p;
19398 if (!at_zv_p
19399 && w->cursor.hpos >= 0
19400 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19401 w->cursor.vpos))
19402 {
19403 struct glyph_row *candidate =
19404 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19405 struct glyph *g =
19406 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19407 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19408
19409 exact_match_p =
19410 (BUFFERP (g->object) && g->charpos == PT)
19411 || (NILP (g->object)
19412 && (g->charpos == PT
19413 || (g->charpos == 0 && endpos - 1 == PT)));
19414
19415
19416
19417
19418 if (!exact_match_p && pt_invis)
19419 exact_match_p = true;
19420 }
19421 if (at_zv_p || exact_match_p)
19422 {
19423 rc = CURSOR_MOVEMENT_SUCCESS;
19424 break;
19425 }
19426 }
19427 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19428 break;
19429 ++row;
19430 }
19431 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19432 || row->continued_p)
19433 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19434 || (MATRIX_ROW_START_CHARPOS (row) == PT
19435 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19436
19437
19438
19439 if (rc != CURSOR_MOVEMENT_SUCCESS
19440 && !(rv
19441 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19442 && !row->continued_p))
19443 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19444 else if (rv)
19445 rc = CURSOR_MOVEMENT_SUCCESS;
19446 }
19447 else
19448 {
19449 do
19450 {
19451 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19452 {
19453 rc = CURSOR_MOVEMENT_SUCCESS;
19454 break;
19455 }
19456 ++row;
19457 }
19458 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19459 && MATRIX_ROW_START_CHARPOS (row) == PT
19460 && cursor_row_p (row));
19461 }
19462 }
19463 }
19464
19465 return rc;
19466 }
19467
19468
19469 void
19470 set_vertical_scroll_bar (struct window *w)
19471 {
19472 ptrdiff_t start, end, whole;
19473
19474
19475
19476
19477
19478
19479
19480
19481 if (!MINI_WINDOW_P (w)
19482 || (w == XWINDOW (minibuf_window)
19483 && NILP (echo_area_buffer[0])))
19484 {
19485 struct buffer *buf = XBUFFER (w->contents);
19486
19487 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19488 start = marker_position (w->start) - BUF_BEGV (buf);
19489 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19490
19491
19492
19493
19494 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19495 {
19496 struct it it;
19497 struct text_pos start_pos;
19498 struct buffer *obuf = current_buffer;
19499
19500
19501
19502 set_buffer_internal_1 (XBUFFER (w->contents));
19503 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19504 start_display (&it, w, start_pos);
19505 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19506 MOVE_TO_X | MOVE_TO_Y);
19507 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19508 set_buffer_internal_1 (obuf);
19509 }
19510
19511 if (end < start)
19512 end = start;
19513 if (whole < (end - start))
19514 whole = end - start;
19515 }
19516 else
19517 start = end = whole = 0;
19518
19519
19520 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19521 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19522 (w, end - start, whole, start);
19523 }
19524
19525
19526 void
19527 set_horizontal_scroll_bar (struct window *w)
19528 {
19529 int start, end, whole, portion;
19530
19531 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19532 {
19533 struct buffer *b = XBUFFER (w->contents);
19534 struct buffer *old_buffer = NULL;
19535 struct it it;
19536 struct text_pos startp;
19537
19538 if (b != current_buffer)
19539 {
19540 old_buffer = current_buffer;
19541 set_buffer_internal (b);
19542 }
19543
19544 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19545 start_display (&it, w, startp);
19546 it.last_visible_x = INT_MAX;
19547 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19548 MOVE_TO_X | MOVE_TO_Y);
19549
19550
19551
19552
19553 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19554 end = start + window_box_width (w, TEXT_AREA);
19555 portion = end - start;
19556
19557
19558
19559
19560 whole = max (whole, end);
19561
19562 if (it.bidi_p)
19563 {
19564 Lisp_Object pdir;
19565
19566 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19567 if (EQ (pdir, Qright_to_left))
19568 {
19569 start = whole - end;
19570 end = start + portion;
19571 }
19572 }
19573
19574 if (old_buffer)
19575 set_buffer_internal (old_buffer);
19576 }
19577 else
19578 start = end = whole = portion = 0;
19579
19580 w->hscroll_whole = whole;
19581
19582
19583 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19584 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19585 (w, portion, whole, start);
19586 }
19587
19588
19589
19590 static bool
19591 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19592 {
19593 if (!make_window_start_visible)
19594 return true;
19595
19596 struct window *w = XWINDOW (window);
19597 struct frame *f = XFRAME (w->frame);
19598 Lisp_Object startpos = make_fixnum (startp);
19599 Lisp_Object invprop, disp_spec;
19600 struct text_pos ignored;
19601
19602
19603 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19604 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19605 return false;
19606
19607
19608 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19609 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19610 FRAME_WINDOW_P (f)) > 0)
19611 return false;
19612
19613 return true;
19614 }
19615
19616 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19617 0, 0, 0,
19618 doc:
19619
19620 )
19621 (void)
19622 {
19623 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19624 }
19625
19626
19627
19628
19629
19630
19631
19632
19633
19634
19635
19636
19637
19638
19639
19640
19641
19642
19643
19644
19645
19646
19647
19648
19649
19650
19651
19652
19653
19654
19655
19656
19657
19658
19659
19660
19661
19662
19663
19664
19665
19666
19667
19668
19669
19670
19671
19672
19673
19674
19675
19676 static void
19677 redisplay_window (Lisp_Object window, bool just_this_one_p)
19678 {
19679 struct window *w = XWINDOW (window);
19680 struct frame *f = XFRAME (w->frame);
19681 struct buffer *buffer = XBUFFER (w->contents);
19682 struct buffer *old = current_buffer;
19683 struct text_pos lpoint, opoint, startp;
19684 bool update_mode_line;
19685 int tem;
19686 struct it it;
19687
19688 bool current_matrix_up_to_date_p = false;
19689 bool used_current_matrix_p = false;
19690
19691
19692 bool buffer_unchanged_p = false;
19693 bool temp_scroll_step = false;
19694 specpdl_ref count = SPECPDL_INDEX ();
19695 int rc;
19696 int centering_position = -1;
19697 bool last_line_misfit = false;
19698 ptrdiff_t beg_unchanged, end_unchanged;
19699 int frame_line_height, margin;
19700 bool use_desired_matrix;
19701 void *itdata = NULL;
19702
19703 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19704 opoint = lpoint;
19705
19706 #ifdef GLYPH_DEBUG
19707 *w->desired_matrix->method = 0;
19708 #endif
19709
19710 if (!just_this_one_p && needs_no_redisplay (w))
19711 return;
19712
19713
19714 eassert (XMARKER (w->start)->buffer == buffer);
19715 eassert (XMARKER (w->pointm)->buffer == buffer);
19716
19717 reconsider_clip_changes (w);
19718 frame_line_height = default_line_pixel_height (w);
19719 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19720
19721
19722
19723 update_mode_line = (w->update_mode_line
19724 || update_mode_lines
19725 || buffer->clip_changed
19726 || buffer->prevent_redisplay_optimizations_p);
19727
19728 if (!just_this_one_p)
19729
19730
19731 w->must_be_updated_p = true;
19732
19733 if (MINI_WINDOW_P (w))
19734 {
19735 if (w == XWINDOW (echo_area_window)
19736 && !NILP (echo_area_buffer[0]))
19737 {
19738 if (update_mode_line)
19739
19740
19741 goto finish_menu_bars;
19742 else
19743
19744 goto finish_scroll_bars;
19745 }
19746 else if ((w != XWINDOW (minibuf_window)
19747 || minibuf_level == 0)
19748
19749 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19750
19751
19752 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19753 {
19754
19755
19756 int yb = window_text_bottom_y (w);
19757 struct glyph_row *row;
19758 int y;
19759
19760 for (y = 0, row = w->desired_matrix->rows;
19761 y < yb;
19762 y += row->height, ++row)
19763 blank_row (w, row, y);
19764 goto finish_scroll_bars;
19765 }
19766 else if (minibuf_level >= 1)
19767 {
19768
19769
19770
19771 resize_mini_window (w, false);
19772 }
19773
19774 clear_glyph_matrix (w->desired_matrix);
19775 }
19776
19777
19778
19779
19780
19781 set_buffer_internal_1 (XBUFFER (w->contents));
19782
19783 current_matrix_up_to_date_p
19784 = (w->window_end_valid
19785 && !current_buffer->clip_changed
19786 && !current_buffer->prevent_redisplay_optimizations_p
19787 && !window_outdated (w)
19788 && !composition_break_at_point
19789 && !hscrolling_current_line_p (w));
19790
19791 beg_unchanged = BEG_UNCHANGED;
19792 end_unchanged = END_UNCHANGED;
19793
19794 SET_TEXT_POS (opoint, PT, PT_BYTE);
19795
19796 specbind (Qinhibit_point_motion_hooks, Qt);
19797
19798 buffer_unchanged_p
19799 = (w->window_end_valid
19800 && !current_buffer->clip_changed
19801 && !window_outdated (w));
19802
19803
19804
19805 if (windows_or_buffers_changed)
19806 {
19807
19808
19809 if (XMARKER (w->start)->buffer == current_buffer)
19810 compute_window_start_on_continuation_line (w);
19811
19812 w->window_end_valid = false;
19813
19814
19815 current_matrix_up_to_date_p = false;
19816 }
19817
19818
19819 CHECK_WINDOW_END (w);
19820 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19821 emacs_abort ();
19822 if (BYTEPOS (opoint) < CHARPOS (opoint))
19823 emacs_abort ();
19824
19825 if (mode_line_update_needed (w))
19826 update_mode_line = true;
19827
19828
19829
19830 if (!EQ (window, selected_window))
19831 {
19832 ptrdiff_t new_pt = marker_position (w->pointm);
19833 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19834
19835 if (new_pt < BEGV)
19836 {
19837 new_pt = BEGV;
19838 new_pt_byte = BEGV_BYTE;
19839 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19840 }
19841 else if (new_pt > (ZV - 1))
19842 {
19843 new_pt = ZV;
19844 new_pt_byte = ZV_BYTE;
19845 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19846 }
19847
19848
19849 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19850 }
19851
19852
19853
19854
19855
19856
19857 if (current_buffer->width_run_cache
19858 || (current_buffer->base_buffer
19859 && current_buffer->base_buffer->width_run_cache))
19860 {
19861 struct Lisp_Char_Table *disptab = buffer_display_table ();
19862
19863 if (! disptab_matches_widthtab
19864 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19865 {
19866 struct buffer *buf = current_buffer;
19867
19868 if (buf->base_buffer)
19869 buf = buf->base_buffer;
19870 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19871 recompute_width_table (current_buffer, disptab);
19872 }
19873 }
19874
19875
19876 if (!NILP (Vlong_line_threshold)
19877 && !current_buffer->long_line_optimizations_p
19878 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19879 || current_buffer->clip_changed))
19880 {
19881 ptrdiff_t cur, next, found, max = 0, threshold;
19882 threshold = XFIXNUM (Vlong_line_threshold);
19883 for (cur = BEGV; cur < ZV; cur = next)
19884 {
19885 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19886 &found, NULL, true);
19887 if (next - cur > max) max = next - cur;
19888 if (!found || max > threshold) break;
19889 }
19890 if (max > threshold)
19891 current_buffer->long_line_optimizations_p = true;
19892 }
19893
19894
19895 if (XMARKER (w->start)->buffer != current_buffer)
19896 goto recenter;
19897
19898 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19899
19900
19901
19902 if ((w->optional_new_start || window_frozen_p (w))
19903 && CHARPOS (startp) >= BEGV
19904 && CHARPOS (startp) <= ZV)
19905 {
19906 ptrdiff_t it_charpos;
19907
19908 w->optional_new_start = false;
19909 if (!w->force_start)
19910 {
19911 start_display (&it, w, startp);
19912 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19913 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19914
19915
19916 it_charpos = IT_CHARPOS (it);
19917
19918
19919
19920
19921
19922 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19923 {
19924 if (it_charpos == PT)
19925 w->force_start = true;
19926
19927 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19928 w->force_start = true;
19929 #ifdef GLYPH_DEBUG
19930 if (w->force_start)
19931 {
19932 if (window_frozen_p (w))
19933 debug_method_add (w, "set force_start from frozen window start");
19934 else
19935 debug_method_add (w, "set force_start from optional_new_start");
19936 }
19937 #endif
19938 }
19939 }
19940 }
19941
19942 force_start:
19943
19944
19945
19946 if (w->force_start)
19947 {
19948
19949 int new_vpos = -1;
19950
19951 w->force_start = false;
19952
19953
19954
19955
19956 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19957 w->vscroll = 0;
19958
19959 w->preserve_vscroll_p = false;
19960 w->window_end_valid = false;
19961
19962
19963 if (!buffer_unchanged_p)
19964 w->base_line_number = 0;
19965
19966
19967
19968
19969
19970
19971
19972
19973 if (!update_mode_line
19974 || ! NILP (Vwindow_scroll_functions))
19975 {
19976 update_mode_line = true;
19977 w->update_mode_line = true;
19978 startp = run_window_scroll_functions (window, startp);
19979 }
19980
19981 if (CHARPOS (startp) < BEGV)
19982 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
19983 else if (CHARPOS (startp) > ZV)
19984 SET_TEXT_POS (startp, ZV, ZV_BYTE);
19985
19986
19987
19988 if (!window_start_acceptable_p (window, CHARPOS (startp)))
19989 goto ignore_start;
19990
19991
19992
19993
19994
19995
19996 clear_glyph_matrix (w->desired_matrix);
19997 if (!try_window (window, startp, 0))
19998 {
19999 w->force_start = true;
20000 clear_glyph_matrix (w->desired_matrix);
20001 goto need_larger_matrices;
20002 }
20003
20004 if (w->cursor.vpos < 0)
20005 {
20006
20007
20008
20009
20010
20011 struct glyph_row *r = NULL;
20012 Lisp_Object invprop =
20013 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20014 Qnil, NULL);
20015
20016 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
20017 {
20018 ptrdiff_t alt_pt;
20019 Lisp_Object invprop_end =
20020 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20021 Qnil, Qnil);
20022
20023 if (FIXNATP (invprop_end))
20024 alt_pt = XFIXNAT (invprop_end);
20025 else
20026 alt_pt = ZV;
20027 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
20028 NULL, 0);
20029 }
20030 if (r)
20031 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
20032 else
20033 new_vpos = window_box_height (w) / 2;
20034 }
20035
20036 if (!cursor_row_fully_visible_p (w, false, false, false))
20037 {
20038
20039
20040 new_vpos = window_box_height (w);
20041
20042
20043
20044
20045
20046
20047 if (new_vpos >= w->cursor.y)
20048 {
20049 w->cursor.vpos = -1;
20050 clear_glyph_matrix (w->desired_matrix);
20051 goto try_to_scroll;
20052 }
20053 }
20054 else if (w->cursor.vpos >= 0)
20055 {
20056
20057
20058
20059 int pixel_margin = margin * frame_line_height;
20060 bool tab_line = window_wants_tab_line (w);
20061 bool header_line = window_wants_header_line (w);
20062
20063
20064
20065
20066
20067 if (w->cursor.vpos < margin + tab_line + header_line)
20068 {
20069 w->cursor.vpos = -1;
20070 clear_glyph_matrix (w->desired_matrix);
20071 goto try_to_scroll;
20072 }
20073 else
20074 {
20075 int window_height = window_box_height (w);
20076
20077 if (tab_line)
20078 window_height += CURRENT_TAB_LINE_HEIGHT (w);
20079 if (header_line)
20080 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
20081 if (w->cursor.y >= window_height - pixel_margin)
20082 {
20083 w->cursor.vpos = -1;
20084 clear_glyph_matrix (w->desired_matrix);
20085 goto try_to_scroll;
20086 }
20087 }
20088 }
20089
20090
20091
20092 if (new_vpos >= 0)
20093 {
20094 struct glyph_row *row;
20095
20096 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
20097 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
20098 && !row->ends_at_zv_p)
20099 ++row;
20100
20101 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
20102 MATRIX_ROW_START_BYTEPOS (row));
20103
20104 if (w != XWINDOW (selected_window))
20105 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
20106 else if (current_buffer == old)
20107 SET_TEXT_POS (lpoint, PT, PT_BYTE);
20108
20109 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
20110
20111
20112
20113
20114
20115
20116
20117 w->redisplay = false;
20118 XBUFFER (w->contents)->text->redisplay = false;
20119 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
20120
20121 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
20122 || ((EQ (Vdisplay_line_numbers, Qrelative)
20123 || EQ (Vdisplay_line_numbers, Qvisual))
20124 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
20125 {
20126
20127
20128
20129
20130 clear_glyph_matrix (w->desired_matrix);
20131 if (!try_window (window, startp, 0))
20132 goto need_larger_matrices;
20133 }
20134 }
20135 if (w->cursor.vpos < 0
20136 || !cursor_row_fully_visible_p (w, false, false, false))
20137 {
20138 clear_glyph_matrix (w->desired_matrix);
20139 goto try_to_scroll;
20140 }
20141
20142 #ifdef GLYPH_DEBUG
20143 debug_method_add (w, "forced window start");
20144 #endif
20145 goto done;
20146 }
20147
20148 ignore_start:
20149
20150
20151
20152
20153 if (current_matrix_up_to_date_p
20154 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
20155 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
20156 {
20157 switch (rc)
20158 {
20159 case CURSOR_MOVEMENT_SUCCESS:
20160 used_current_matrix_p = true;
20161 goto done;
20162
20163 case CURSOR_MOVEMENT_MUST_SCROLL:
20164 goto try_to_scroll;
20165
20166 default:
20167 emacs_abort ();
20168 }
20169 }
20170
20171
20172
20173 else if (w->start_at_line_beg
20174 && ((CHARPOS (startp) > BEGV
20175 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20176 || (CHARPOS (startp) >= BEGV
20177 && CHARPOS (startp) <= ZV
20178 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20179 {
20180 #ifdef GLYPH_DEBUG
20181 debug_method_add (w, "recenter 1");
20182 #endif
20183 goto recenter;
20184 }
20185
20186
20187
20188
20189 else if ((tem = try_window_id (w)) != 0)
20190 {
20191 #ifdef GLYPH_DEBUG
20192 debug_method_add (w, "try_window_id %d", tem);
20193 #endif
20194
20195 if (f->fonts_changed)
20196 goto need_larger_matrices;
20197 if (tem > 0)
20198 goto done;
20199
20200
20201
20202 }
20203 else if (CHARPOS (startp) >= BEGV
20204 && CHARPOS (startp) <= ZV
20205 && PT >= CHARPOS (startp)
20206 && (CHARPOS (startp) < ZV
20207
20208 || CHARPOS (startp) == BEGV
20209 || !window_outdated (w)))
20210 {
20211 int d1, d2, d5, d6;
20212 int rtop, rbot;
20213
20214
20215
20216
20217
20218
20219
20220
20221
20222
20223 if (!w->start_at_line_beg
20224 && NILP (track_mouse)
20225 && CHARPOS (startp) > BEGV
20226 && CHARPOS (startp) > BEG + beg_unchanged
20227 && CHARPOS (startp) <= Z - end_unchanged
20228
20229
20230
20231
20232
20233 && XMARKER (w->start)->buffer == current_buffer
20234 && compute_window_start_on_continuation_line (w)
20235
20236
20237
20238
20239
20240
20241 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20242
20243
20244 && (rtop != 0) == (rbot != 0))
20245 {
20246 w->force_start = true;
20247 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20248 #ifdef GLYPH_DEBUG
20249 debug_method_add (w, "recomputed window start in continuation line");
20250 #endif
20251 goto force_start;
20252 }
20253
20254
20255
20256
20257 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20258 {
20259 #ifdef GLYPH_DEBUG
20260 debug_method_add (w, "recenter 2");
20261 #endif
20262 goto recenter;
20263 }
20264
20265 #ifdef GLYPH_DEBUG
20266 debug_method_add (w, "same window start");
20267 #endif
20268
20269
20270
20271 if (!current_matrix_up_to_date_p
20272
20273
20274
20275 || !NILP (Vwindow_scroll_functions)
20276 || MINI_WINDOW_P (w)
20277 || !(used_current_matrix_p
20278 = try_window_reusing_current_matrix (w)))
20279 {
20280 IF_DEBUG (debug_method_add (w, "1"));
20281 clear_glyph_matrix (w->desired_matrix);
20282 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20283
20284
20285
20286 goto try_to_scroll;
20287 }
20288
20289 if (f->fonts_changed)
20290 goto need_larger_matrices;
20291
20292 if (w->cursor.vpos >= 0)
20293 {
20294 if (!just_this_one_p
20295 || current_buffer->clip_changed
20296 || BEG_UNCHANGED < CHARPOS (startp))
20297
20298 w->base_line_number = 0;
20299
20300 if (!cursor_row_fully_visible_p (w, true, false, false))
20301 {
20302 clear_glyph_matrix (w->desired_matrix);
20303 last_line_misfit = true;
20304 }
20305
20306 else
20307 goto done;
20308 }
20309 else
20310 clear_glyph_matrix (w->desired_matrix);
20311 }
20312
20313 try_to_scroll:
20314
20315
20316 if (!update_mode_line)
20317 {
20318 update_mode_line = true;
20319 w->update_mode_line = true;
20320 }
20321
20322
20323 if ((0 < scroll_conservatively
20324
20325
20326
20327
20328 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20329 || 0 < emacs_scroll_step
20330 || temp_scroll_step
20331 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20332 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20333 && CHARPOS (startp) >= BEGV
20334 && CHARPOS (startp) <= ZV)
20335 {
20336
20337
20338 int ss = try_scrolling (window, just_this_one_p,
20339 ((scroll_minibuffer_conservatively
20340 && MINI_WINDOW_P (w))
20341 ? SCROLL_LIMIT + 1
20342 : scroll_conservatively),
20343 emacs_scroll_step,
20344 temp_scroll_step, last_line_misfit);
20345 switch (ss)
20346 {
20347 case SCROLLING_SUCCESS:
20348 goto done;
20349
20350 case SCROLLING_NEED_LARGER_MATRICES:
20351 goto need_larger_matrices;
20352
20353 case SCROLLING_FAILED:
20354 break;
20355
20356 default:
20357 emacs_abort ();
20358 }
20359 }
20360
20361
20362
20363
20364 recenter:
20365
20366 #ifdef GLYPH_DEBUG
20367 debug_method_add (w, "recenter");
20368 #endif
20369
20370
20371 if (!buffer_unchanged_p)
20372 w->base_line_number = 0;
20373
20374
20375 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20376 it.current_y = it.last_visible_y;
20377 if (centering_position < 0)
20378 {
20379 ptrdiff_t margin_pos = CHARPOS (startp);
20380 Lisp_Object aggressive;
20381 bool scrolling_up;
20382
20383
20384
20385 if (margin
20386
20387
20388
20389
20390
20391
20392 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20393 {
20394 struct it it1;
20395 void *it1data = NULL;
20396
20397 SAVE_IT (it1, it, it1data);
20398 start_display (&it1, w, startp);
20399 move_it_vertically (&it1, margin * frame_line_height);
20400 margin_pos = IT_CHARPOS (it1);
20401 RESTORE_IT (&it, &it, it1data);
20402 }
20403 scrolling_up = PT > margin_pos;
20404 aggressive =
20405 scrolling_up
20406 ? BVAR (current_buffer, scroll_up_aggressively)
20407 : BVAR (current_buffer, scroll_down_aggressively);
20408
20409 if (!MINI_WINDOW_P (w)
20410 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20411 {
20412 int pt_offset = 0;
20413
20414
20415
20416 if (!scroll_conservatively && NUMBERP (aggressive))
20417 {
20418 double float_amount = XFLOATINT (aggressive);
20419
20420 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20421 if (pt_offset == 0 && float_amount > 0)
20422 pt_offset = 1;
20423 if (pt_offset && margin > 0)
20424 margin -= 1;
20425 }
20426
20427
20428
20429 if (scrolling_up)
20430 {
20431 centering_position = it.last_visible_y;
20432 if (pt_offset)
20433 centering_position -= pt_offset;
20434 centering_position -=
20435 (frame_line_height * (1 + margin + last_line_misfit)
20436 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20437
20438
20439 if (centering_position < margin * frame_line_height)
20440 centering_position = margin * frame_line_height;
20441 }
20442 else
20443 centering_position = margin * frame_line_height + pt_offset;
20444 }
20445 else
20446
20447
20448 centering_position = window_box_height (w) / 2;
20449 }
20450 if (current_buffer->long_line_optimizations_p
20451 && it.line_wrap == TRUNCATE)
20452 {
20453
20454
20455
20456 int nlines = centering_position / frame_line_height;
20457
20458 while (nlines-- && IT_CHARPOS (it) > BEGV)
20459 back_to_previous_visible_line_start (&it);
20460 reseat_1 (&it, it.current.pos, true);
20461 }
20462 else
20463 move_it_vertically_backward (&it, centering_position);
20464
20465 eassert (IT_CHARPOS (it) >= BEGV);
20466
20467
20468
20469
20470
20471
20472 if (it.current_y <= 0)
20473 {
20474 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20475 move_it_vertically_backward (&it, 0);
20476 it.current_y = 0;
20477 }
20478
20479 it.current_x = it.hpos = 0;
20480
20481
20482
20483
20484 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20485
20486
20487 startp = run_window_scroll_functions (window, it.current.pos);
20488
20489
20490
20491
20492 itdata = bidi_shelve_cache ();
20493
20494
20495 use_desired_matrix = false;
20496 if (!current_matrix_up_to_date_p
20497 || windows_or_buffers_changed
20498 || f->cursor_type_changed
20499
20500
20501 || !NILP (Vwindow_scroll_functions)
20502 || !just_this_one_p
20503 || MINI_WINDOW_P (w)
20504 || !(used_current_matrix_p
20505 = try_window_reusing_current_matrix (w)))
20506 use_desired_matrix = (try_window (window, startp, 0) == 1);
20507
20508 bidi_unshelve_cache (itdata, false);
20509
20510
20511
20512
20513 if (f->fonts_changed)
20514 goto need_larger_matrices;
20515
20516
20517
20518
20519
20520
20521 if (w->cursor.vpos < 0)
20522 {
20523 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20524 {
20525 clear_glyph_matrix (w->desired_matrix);
20526 move_it_by_lines (&it, 1);
20527 try_window (window, it.current.pos, 0);
20528 }
20529 else if (PT < IT_CHARPOS (it))
20530 {
20531 clear_glyph_matrix (w->desired_matrix);
20532 move_it_by_lines (&it, -1);
20533 try_window (window, it.current.pos, 0);
20534 }
20535 else if (scroll_conservatively > SCROLL_LIMIT
20536 && (it.method == GET_FROM_STRING
20537 || overlay_touches_p (IT_CHARPOS (it)))
20538 && IT_CHARPOS (it) < ZV)
20539 {
20540
20541
20542
20543
20544
20545
20546
20547
20548 ptrdiff_t pos0 = IT_CHARPOS (it);
20549
20550 clear_glyph_matrix (w->desired_matrix);
20551 do {
20552 move_it_by_lines (&it, 1);
20553 } while (IT_CHARPOS (it) == pos0);
20554 try_window (window, it.current.pos, 0);
20555 }
20556 else
20557 {
20558
20559 }
20560 }
20561
20562
20563
20564
20565
20566
20567 if (w->cursor.vpos < 0)
20568 {
20569
20570
20571
20572
20573 struct glyph_matrix *matrix =
20574 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20575
20576 struct glyph_row *row =
20577 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20578
20579
20580
20581
20582
20583
20584
20585 if (!row)
20586 {
20587 Lisp_Object val =
20588 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20589 Qnil, NULL);
20590
20591 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20592 {
20593 ptrdiff_t alt_pos;
20594 Lisp_Object invis_end =
20595 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20596 Qnil, Qnil);
20597
20598 if (FIXNATP (invis_end))
20599 alt_pos = XFIXNAT (invis_end);
20600 else
20601 alt_pos = ZV;
20602 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20603 }
20604 }
20605
20606
20607
20608 if (!row)
20609 {
20610 row = matrix->rows;
20611
20612 if (row->tab_line_p)
20613 ++row;
20614 if (row->mode_line_p)
20615 ++row;
20616 }
20617 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20618 }
20619
20620 if (!cursor_row_fully_visible_p (w, false, false, false))
20621 {
20622
20623 if (w->vscroll)
20624 {
20625 w->vscroll = 0;
20626 clear_glyph_matrix (w->desired_matrix);
20627 goto recenter;
20628 }
20629
20630
20631
20632
20633
20634 if (scroll_conservatively > SCROLL_LIMIT)
20635 {
20636 int window_total_lines
20637 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20638 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20639
20640 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20641 clear_glyph_matrix (w->desired_matrix);
20642 if (1 == try_window (window, it.current.pos,
20643 TRY_WINDOW_CHECK_MARGINS))
20644 goto done;
20645 }
20646
20647
20648
20649
20650 if (centering_position == 0)
20651 goto done;
20652
20653 clear_glyph_matrix (w->desired_matrix);
20654 centering_position = 0;
20655 goto recenter;
20656 }
20657
20658 done:
20659
20660 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20661 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20662 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20663
20664
20665 if ((update_mode_line
20666
20667
20668
20669
20670 || (!just_this_one_p
20671 && !FRAME_WINDOW_P (f)
20672 && !WINDOW_FULL_WIDTH_P (w))
20673
20674 || w->base_line_pos > 0
20675
20676 || (w->column_number_displayed != -1
20677 && (w->column_number_displayed != current_column ())))
20678
20679 && (window_wants_mode_line (w)
20680 || window_wants_header_line (w)
20681 || window_wants_tab_line (w)))
20682 {
20683 specpdl_ref count1 = SPECPDL_INDEX ();
20684
20685 specbind (Qinhibit_quit, Qt);
20686 display_mode_lines (w);
20687 unbind_to (count1, Qnil);
20688
20689
20690
20691 if (window_wants_mode_line (w)
20692 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20693 {
20694 f->fonts_changed = true;
20695 w->mode_line_height = -1;
20696 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20697 = DESIRED_MODE_LINE_HEIGHT (w);
20698 }
20699
20700
20701
20702 if (window_wants_tab_line (w)
20703 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20704 {
20705 f->fonts_changed = true;
20706 w->tab_line_height = -1;
20707 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20708 = DESIRED_TAB_LINE_HEIGHT (w);
20709 }
20710
20711
20712
20713 if (window_wants_header_line (w)
20714 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20715 {
20716 f->fonts_changed = true;
20717 w->header_line_height = -1;
20718 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20719 = DESIRED_HEADER_LINE_HEIGHT (w);
20720 }
20721
20722 if (f->fonts_changed)
20723 goto need_larger_matrices;
20724 }
20725
20726 if (!line_number_displayed && w->base_line_pos != -1)
20727 {
20728 w->base_line_pos = 0;
20729 w->base_line_number = 0;
20730 }
20731
20732 finish_menu_bars:
20733
20734
20735
20736 if (update_mode_line
20737 && EQ (FRAME_SELECTED_WINDOW (f), window))
20738 {
20739 bool redisplay_menu_p;
20740
20741 if (FRAME_WINDOW_P (f))
20742 {
20743 #ifdef HAVE_EXT_MENU_BAR
20744 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20745 #else
20746 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20747 #endif
20748 }
20749 else
20750 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20751
20752 if (redisplay_menu_p)
20753 display_menu_bar (w);
20754
20755 #ifdef HAVE_WINDOW_SYSTEM
20756 if (FRAME_WINDOW_P (f))
20757 {
20758 if (WINDOWP (f->tab_bar_window)
20759 && (FRAME_TAB_BAR_LINES (f) > 0
20760 || !NILP (Vauto_resize_tab_bars))
20761 && redisplay_tab_bar (f))
20762 ignore_mouse_drag_p = true;
20763
20764 #ifdef HAVE_EXT_TOOL_BAR
20765 if (FRAME_EXTERNAL_TOOL_BAR (f))
20766 update_frame_tool_bar (f);
20767 #else
20768 if (WINDOWP (f->tool_bar_window)
20769 && (FRAME_TOOL_BAR_LINES (f) > 0
20770 || !NILP (Vauto_resize_tool_bars))
20771 && redisplay_tool_bar (f))
20772 ignore_mouse_drag_p = true;
20773 #endif
20774 }
20775 else
20776 {
20777 if ((FRAME_TAB_BAR_LINES (f) > 0))
20778 display_tab_bar (w);
20779 }
20780
20781 gui_consider_frame_title (w->frame);
20782 #else
20783 if ((FRAME_TAB_BAR_LINES (f) > 0))
20784 display_tab_bar (w);
20785 #endif
20786 }
20787
20788 #ifdef HAVE_WINDOW_SYSTEM
20789 if (FRAME_WINDOW_P (f)
20790 && update_window_fringes (w, (just_this_one_p
20791 || (!used_current_matrix_p && !overlay_arrow_seen)
20792 || w->pseudo_window_p)))
20793 {
20794 update_begin (f);
20795 block_input ();
20796 if (draw_window_fringes (w, true))
20797 {
20798 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20799 gui_draw_right_divider (w);
20800 else
20801 gui_draw_vertical_border (w);
20802 }
20803 unblock_input ();
20804 update_end (f);
20805 }
20806
20807 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20808 gui_draw_bottom_divider (w);
20809 #endif
20810
20811
20812
20813
20814
20815 need_larger_matrices:
20816 ;
20817 finish_scroll_bars:
20818
20819 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20820 {
20821 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20822
20823 set_vertical_scroll_bar (w);
20824
20825 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20826
20827 set_horizontal_scroll_bar (w);
20828
20829
20830
20831 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20832 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20833 }
20834
20835
20836
20837
20838 if (CHARPOS (opoint) < BEGV)
20839 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20840 else if (CHARPOS (opoint) > ZV)
20841 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20842 else
20843 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20844
20845 set_buffer_internal_1 (old);
20846
20847
20848 if (CHARPOS (lpoint) <= ZV)
20849 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20850
20851 unbind_to (count, Qnil);
20852 }
20853
20854
20855
20856
20857
20858
20859
20860
20861
20862
20863
20864
20865
20866
20867
20868
20869
20870
20871
20872
20873 int
20874 try_window (Lisp_Object window, struct text_pos pos, int flags)
20875 {
20876 struct window *w = XWINDOW (window);
20877 struct it it;
20878 struct glyph_row *last_text_row = NULL;
20879 struct frame *f = XFRAME (w->frame);
20880 int cursor_vpos = w->cursor.vpos;
20881
20882
20883 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20884
20885
20886 w->cursor.vpos = -1;
20887 overlay_arrow_seen = false;
20888
20889
20890 start_display (&it, w, pos);
20891 it.glyph_row->reversed_p = false;
20892
20893
20894 while (it.current_y < it.last_visible_y)
20895 {
20896 int last_row_scale = it.w->nrows_scale_factor;
20897 int last_col_scale = it.w->ncols_scale_factor;
20898 if (display_line (&it, cursor_vpos))
20899 last_text_row = it.glyph_row - 1;
20900 if (f->fonts_changed
20901 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20902
20903
20904 && last_row_scale == it.w->nrows_scale_factor
20905 && last_col_scale == it.w->ncols_scale_factor))
20906 return 0;
20907 }
20908
20909
20910
20911 ptrdiff_t it_charpos = IT_CHARPOS (it);
20912
20913
20914
20915
20916 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20917 && w->vscroll == 0
20918 && !MINI_WINDOW_P (w))
20919 {
20920 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20921 int bot_scroll_margin = top_scroll_margin;
20922 if (window_wants_header_line (w))
20923 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20924 if (window_wants_tab_line (w))
20925 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20926 start_display (&it, w, pos);
20927
20928 if ((w->cursor.y >= 0
20929 && w->cursor.y < top_scroll_margin
20930 && CHARPOS (pos) > BEGV)
20931
20932
20933
20934
20935 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20936 - bot_scroll_margin - 1))
20937 {
20938 w->cursor.vpos = -1;
20939 clear_glyph_matrix (w->desired_matrix);
20940 return -1;
20941 }
20942 }
20943
20944
20945 if (w->window_end_pos <= 0 && Z != it_charpos)
20946 w->update_mode_line = true;
20947
20948
20949
20950
20951 if (last_text_row)
20952 {
20953 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20954 adjust_window_ends (w, last_text_row, false);
20955 eassert
20956 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20957 w->window_end_vpos)));
20958 }
20959 else
20960 {
20961 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20962 w->window_end_pos = Z - ZV;
20963 w->window_end_vpos = 0;
20964 }
20965
20966
20967 w->window_end_valid = false;
20968 return 1;
20969 }
20970
20971
20972
20973
20974
20975
20976
20977
20978
20979
20980
20981
20982 static bool
20983 try_window_reusing_current_matrix (struct window *w)
20984 {
20985 struct frame *f = XFRAME (w->frame);
20986 struct glyph_row *bottom_row;
20987 struct it it;
20988 struct run run;
20989 struct text_pos start, new_start;
20990 int nrows_scrolled, i;
20991 struct glyph_row *last_text_row;
20992 struct glyph_row *last_reused_text_row;
20993 struct glyph_row *start_row;
20994 int start_vpos, min_y, max_y;
20995
20996 #ifdef GLYPH_DEBUG
20997 if (inhibit_try_window_reusing)
20998 return false;
20999 #endif
21000
21001 if (
21002 !FRAME_WINDOW_P (f)
21003
21004
21005 || windows_or_buffers_changed
21006 || f->cursor_type_changed
21007
21008
21009
21010 || overlay_arrow_in_current_buffer_p ())
21011 return false;
21012
21013
21014 if (!NILP (Vshow_trailing_whitespace))
21015 return false;
21016
21017
21018 if (window_wants_tab_line (w)
21019 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
21020 return false;
21021
21022
21023 if (window_wants_header_line (w)
21024 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
21025 return false;
21026
21027
21028
21029 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21030 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
21031 return false;
21032
21033
21034 clear_glyph_matrix (w->desired_matrix);
21035
21036
21037
21038
21039 if (!NILP (Vdisplay_line_numbers))
21040 return false;
21041
21042
21043
21044
21045 #ifdef HAVE_NTGUI
21046 if (w32_use_visible_system_caret)
21047 return false;
21048 #endif
21049
21050
21051
21052 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
21053 start = start_row->minpos;
21054 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21055
21056 if (CHARPOS (new_start) <= CHARPOS (start))
21057 {
21058
21059
21060
21061
21062 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
21063 return false;
21064
21065 IF_DEBUG (debug_method_add (w, "twu1"));
21066
21067
21068
21069
21070
21071 start_display (&it, w, new_start);
21072 w->cursor.vpos = -1;
21073 last_text_row = last_reused_text_row = NULL;
21074
21075 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21076 {
21077
21078
21079
21080
21081 while (IT_CHARPOS (it) > CHARPOS (start))
21082 {
21083
21084 start_row++;
21085 start = start_row->minpos;
21086
21087 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
21088 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
21089 || CHARPOS (start) == ZV)
21090 {
21091 clear_glyph_matrix (w->desired_matrix);
21092 return false;
21093 }
21094
21095 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21096 }
21097
21098
21099 if (IT_CHARPOS (it) == CHARPOS (start)
21100
21101
21102
21103
21104
21105 && it.current.dpvec_index < 0)
21106 break;
21107
21108 it.glyph_row->reversed_p = false;
21109 if (display_line (&it, -1))
21110 last_text_row = it.glyph_row - 1;
21111
21112 }
21113
21114
21115
21116
21117 if (it.current_y < it.last_visible_y)
21118 {
21119 struct glyph_row *row;
21120
21121
21122 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
21123
21124
21125 if (w->cursor.vpos < 0)
21126 {
21127 int dy = it.current_y - start_row->y;
21128
21129 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21130 row = row_containing_pos (w, PT, row, NULL, dy);
21131 if (row)
21132 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
21133 dy, nrows_scrolled);
21134 else
21135 {
21136 clear_glyph_matrix (w->desired_matrix);
21137 return false;
21138 }
21139 }
21140
21141
21142
21143
21144
21145
21146
21147 run.current_y = start_row->y;
21148 run.desired_y = it.current_y;
21149 run.height = it.last_visible_y - it.current_y;
21150
21151 if (run.height > 0 && run.current_y != run.desired_y)
21152 {
21153 #ifdef HAVE_WINDOW_SYSTEM
21154 update_begin (f);
21155 gui_update_window_begin (w);
21156 FRAME_RIF (f)->clear_window_mouse_face (w);
21157 FRAME_RIF (f)->scroll_run_hook (w, &run);
21158 gui_update_window_end (w, false, false);
21159 update_end (f);
21160 #endif
21161 }
21162
21163
21164 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21165 rotate_matrix (w->current_matrix,
21166 start_vpos,
21167 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21168 nrows_scrolled);
21169
21170
21171 for (i = 0; i < nrows_scrolled; ++i)
21172 (start_row + i)->enabled_p = false;
21173
21174
21175 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21176 max_y = it.last_visible_y;
21177 for (row = start_row + nrows_scrolled;
21178 row < bottom_row;
21179 ++row)
21180 {
21181 row->y = it.current_y;
21182 row->visible_height = row->height;
21183
21184 if (row->y < min_y)
21185 row->visible_height -= min_y - row->y;
21186 if (row->y + row->height > max_y)
21187 row->visible_height -= row->y + row->height - max_y;
21188 if (row->fringe_bitmap_periodic_p)
21189 row->redraw_fringe_bitmaps_p = true;
21190
21191 it.current_y += row->height;
21192
21193 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21194 last_reused_text_row = row;
21195 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21196 break;
21197 }
21198
21199
21200
21201 for (++row; row < bottom_row; ++row)
21202 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21203 }
21204
21205
21206
21207
21208
21209 if (last_reused_text_row)
21210 adjust_window_ends (w, last_reused_text_row, true);
21211 else if (last_text_row)
21212 adjust_window_ends (w, last_text_row, false);
21213 else
21214 {
21215
21216 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21217 w->window_end_pos = Z - ZV;
21218 w->window_end_vpos = 0;
21219 }
21220 w->window_end_valid = false;
21221
21222
21223 w->desired_matrix->no_scrolling_p = true;
21224
21225 #ifdef GLYPH_DEBUG
21226 debug_method_add (w, "try_window_reusing_current_matrix 1");
21227 #endif
21228 return true;
21229 }
21230 else if (CHARPOS (new_start) > CHARPOS (start))
21231 {
21232 struct glyph_row *pt_row, *row;
21233 struct glyph_row *first_reusable_row;
21234 struct glyph_row *first_row_to_display;
21235 int dy;
21236 int yb = window_text_bottom_y (w);
21237
21238
21239
21240 first_reusable_row = start_row;
21241 while (first_reusable_row->enabled_p
21242 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21243 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21244 < CHARPOS (new_start)))
21245 ++first_reusable_row;
21246
21247
21248 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21249 || !first_reusable_row->enabled_p
21250 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21251 != CHARPOS (new_start)))
21252 return false;
21253
21254
21255
21256
21257
21258 pt_row = NULL;
21259 for (first_row_to_display = first_reusable_row;
21260 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21261 ++first_row_to_display)
21262 {
21263 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21264 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21265 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21266 && first_row_to_display->ends_at_zv_p
21267 && pt_row == NULL)))
21268 pt_row = first_row_to_display;
21269 }
21270
21271 if (first_row_to_display->y >= yb)
21272 return false;
21273
21274
21275 init_to_row_start (&it, w, first_row_to_display);
21276
21277 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21278 - start_vpos);
21279 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21280 - nrows_scrolled);
21281 it.current_y = (first_row_to_display->y - first_reusable_row->y
21282 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21283
21284
21285
21286
21287 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21288 if (pt_row == NULL)
21289 w->cursor.vpos = -1;
21290 last_text_row = NULL;
21291 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21292 if (display_line (&it, w->cursor.vpos))
21293 last_text_row = it.glyph_row - 1;
21294
21295
21296
21297 if (pt_row)
21298 {
21299 w->cursor.vpos -= nrows_scrolled;
21300 w->cursor.y -= first_reusable_row->y - start_row->y;
21301 }
21302
21303
21304
21305
21306
21307 if (w->cursor.vpos < 0)
21308 {
21309 clear_glyph_matrix (w->desired_matrix);
21310 return false;
21311 }
21312
21313
21314 run.current_y = first_reusable_row->y;
21315 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21316 run.height = it.last_visible_y - run.current_y;
21317 dy = run.current_y - run.desired_y;
21318
21319 if (run.height)
21320 {
21321 #ifdef HAVE_WINDOW_SYSTEM
21322 update_begin (f);
21323 gui_update_window_begin (w);
21324 FRAME_RIF (f)->clear_window_mouse_face (w);
21325 FRAME_RIF (f)->scroll_run_hook (w, &run);
21326 gui_update_window_end (w, false, false);
21327 update_end (f);
21328 #endif
21329 }
21330
21331
21332 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21333 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21334 max_y = it.last_visible_y;
21335 for (row = first_reusable_row; row < first_row_to_display; ++row)
21336 {
21337 row->y -= dy;
21338 row->visible_height = row->height;
21339 if (row->y < min_y)
21340 row->visible_height -= min_y - row->y;
21341 if (row->y + row->height > max_y)
21342 row->visible_height -= row->y + row->height - max_y;
21343 if (row->fringe_bitmap_periodic_p)
21344 row->redraw_fringe_bitmaps_p = true;
21345 }
21346
21347
21348 eassert (nrows_scrolled > 0);
21349 rotate_matrix (w->current_matrix,
21350 start_vpos,
21351 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21352 -nrows_scrolled);
21353
21354
21355 for (row -= nrows_scrolled; row < bottom_row; ++row)
21356 row->enabled_p = false;
21357
21358
21359
21360 if (pt_row)
21361 {
21362 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21363 row < bottom_row
21364 && PT >= MATRIX_ROW_END_CHARPOS (row)
21365 && !row->ends_at_zv_p;
21366 row++)
21367 {
21368 w->cursor.vpos++;
21369 w->cursor.y = row->y;
21370 }
21371 if (row < bottom_row)
21372 {
21373
21374
21375
21376
21377 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21378 {
21379 if (!set_cursor_from_row (w, row, w->current_matrix,
21380 0, 0, 0, 0))
21381 {
21382 clear_glyph_matrix (w->desired_matrix);
21383 return false;
21384 }
21385 }
21386 else
21387 {
21388 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21389 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21390
21391 for (; glyph < end
21392 && (!BUFFERP (glyph->object)
21393 || glyph->charpos < PT);
21394 glyph++)
21395 {
21396 w->cursor.hpos++;
21397 w->cursor.x += glyph->pixel_width;
21398 }
21399 }
21400 }
21401 }
21402
21403
21404
21405
21406 if (last_text_row)
21407 adjust_window_ends (w, last_text_row, false);
21408 else
21409 w->window_end_vpos -= nrows_scrolled;
21410
21411 w->window_end_valid = false;
21412 w->desired_matrix->no_scrolling_p = true;
21413
21414 #ifdef GLYPH_DEBUG
21415 debug_method_add (w, "try_window_reusing_current_matrix 2");
21416 #endif
21417 return true;
21418 }
21419
21420 return false;
21421 }
21422
21423
21424
21425
21426
21427
21428
21429 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21430 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21431 ptrdiff_t *, ptrdiff_t *);
21432 static struct glyph_row *
21433 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21434 struct glyph_row *);
21435
21436
21437
21438
21439
21440
21441
21442 static struct glyph_row *
21443 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21444 struct glyph_row *start)
21445 {
21446 struct glyph_row *row, *row_found;
21447
21448
21449
21450
21451 row_found = NULL;
21452 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21453 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21454 {
21455 eassert (row->enabled_p);
21456 row_found = row;
21457 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21458 break;
21459 ++row;
21460 }
21461
21462 return row_found;
21463 }
21464
21465
21466
21467
21468
21469
21470
21471
21472
21473
21474
21475
21476 static struct glyph_row *
21477 find_last_unchanged_at_beg_row (struct window *w)
21478 {
21479 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21480 struct glyph_row *row;
21481 struct glyph_row *row_found = NULL;
21482 int yb = window_text_bottom_y (w);
21483
21484
21485 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21486 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21487 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21488 ++row)
21489 {
21490 if (
21491
21492 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21493
21494
21495 && !row->ends_at_zv_p
21496
21497
21498
21499 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21500 && (row->continued_p
21501 || row->exact_window_width_line_p))
21502
21503
21504
21505
21506
21507
21508
21509 && CHARPOS (row->end.pos) <= ZV)
21510 row_found = row;
21511
21512
21513 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21514 break;
21515 }
21516
21517 return row_found;
21518 }
21519
21520
21521
21522
21523
21524
21525
21526
21527
21528
21529
21530
21531
21532
21533 static struct glyph_row *
21534 find_first_unchanged_at_end_row (struct window *w,
21535 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21536 {
21537 struct glyph_row *row;
21538 struct glyph_row *row_found = NULL;
21539
21540 *delta = *delta_bytes = 0;
21541
21542
21543
21544 eassert (w->window_end_valid);
21545
21546
21547
21548
21549 if (w->window_end_pos >= END_UNCHANGED)
21550 return NULL;
21551
21552
21553 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21554
21555
21556 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21557 {
21558
21559
21560
21561
21562
21563 ptrdiff_t Z_old =
21564 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21565 ptrdiff_t Z_BYTE_old =
21566 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21567 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21568 struct glyph_row *first_text_row
21569 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21570
21571 *delta = Z - Z_old;
21572 *delta_bytes = Z_BYTE - Z_BYTE_old;
21573
21574
21575
21576
21577
21578
21579
21580 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21581 last_unchanged_pos_old = last_unchanged_pos - *delta;
21582
21583
21584
21585 for (; row > first_text_row; --row)
21586 {
21587
21588
21589 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21590 break;
21591
21592 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21593 row_found = row;
21594 }
21595 }
21596
21597 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21598
21599 return row_found;
21600 }
21601
21602
21603
21604
21605
21606
21607
21608
21609 static void
21610 sync_frame_with_window_matrix_rows (struct window *w)
21611 {
21612 struct frame *f = XFRAME (w->frame);
21613 struct glyph_row *window_row, *window_row_end, *frame_row;
21614
21615
21616
21617 eassert (BUFFERP (w->contents));
21618 eassert (WINDOW_FULL_WIDTH_P (w));
21619 eassert (!FRAME_WINDOW_P (f));
21620
21621
21622
21623
21624
21625 window_row = w->current_matrix->rows;
21626 window_row_end = window_row + w->current_matrix->nrows;
21627 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21628 while (window_row < window_row_end)
21629 {
21630 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21631 struct glyph *end = window_row->glyphs[LAST_AREA];
21632
21633 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21634 frame_row->glyphs[TEXT_AREA] = start;
21635 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21636 frame_row->glyphs[LAST_AREA] = end;
21637
21638
21639
21640 if (!window_row->enabled_p)
21641 frame_row->enabled_p = false;
21642
21643 ++window_row, ++frame_row;
21644 }
21645 }
21646
21647
21648
21649
21650
21651
21652
21653 struct glyph_row *
21654 row_containing_pos (struct window *w, ptrdiff_t charpos,
21655 struct glyph_row *start, struct glyph_row *end, int dy)
21656 {
21657 struct glyph_row *row = start;
21658 struct glyph_row *best_row = NULL;
21659 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21660 int last_y;
21661
21662
21663 if (row->tab_line_p)
21664 ++row;
21665 if (row->mode_line_p)
21666 ++row;
21667
21668 if ((end && row >= end) || !row->enabled_p)
21669 return NULL;
21670
21671 last_y = window_text_bottom_y (w) - dy;
21672
21673 while (true)
21674 {
21675
21676 if ((end && row >= end) || !row->enabled_p)
21677 return NULL;
21678
21679
21680
21681 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21682 return NULL;
21683
21684
21685 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21686 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21687
21688
21689
21690
21691 && !row_for_charpos_p (row, charpos)))
21692 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21693 {
21694 struct glyph *g;
21695
21696 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21697 || (!best_row && !row->continued_p))
21698 return row;
21699
21700
21701
21702
21703 for (g = row->glyphs[TEXT_AREA];
21704 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21705 g++)
21706 {
21707 if (!STRINGP (g->object))
21708 {
21709 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21710 {
21711 mindif = eabs (g->charpos - charpos);
21712 best_row = row;
21713
21714 if (mindif == 0)
21715 return best_row;
21716 }
21717 }
21718 }
21719 }
21720 else if (best_row && !row->continued_p)
21721 return best_row;
21722 ++row;
21723 }
21724 }
21725
21726
21727
21728
21729
21730
21731
21732
21733
21734
21735
21736
21737
21738
21739
21740
21741
21742
21743
21744
21745
21746
21747
21748
21749
21750
21751
21752
21753
21754
21755
21756
21757
21758
21759
21760
21761
21762
21763
21764
21765
21766
21767
21768
21769 static int
21770 try_window_id (struct window *w)
21771 {
21772 struct frame *f = XFRAME (w->frame);
21773 struct glyph_matrix *current_matrix = w->current_matrix;
21774 struct glyph_matrix *desired_matrix = w->desired_matrix;
21775 struct glyph_row *last_unchanged_at_beg_row;
21776 struct glyph_row *first_unchanged_at_end_row;
21777 struct glyph_row *row;
21778 struct glyph_row *bottom_row;
21779 int bottom_vpos;
21780 struct it it;
21781 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21782 int dvpos, dy;
21783 struct text_pos start_pos;
21784 struct run run;
21785 int first_unchanged_at_end_vpos = 0;
21786 struct glyph_row *last_text_row, *last_text_row_at_end;
21787 struct text_pos start;
21788 ptrdiff_t first_changed_charpos, last_changed_charpos;
21789
21790 #ifdef GLYPH_DEBUG
21791 if (inhibit_try_window_id)
21792 return 0;
21793 #endif
21794
21795
21796 #if false
21797 #define GIVE_UP(X) \
21798 do { \
21799 redisplay_trace ("try_window_id give up %d\n", X); \
21800 return 0; \
21801 } while (false)
21802 #else
21803 #define GIVE_UP(X) return 0
21804 #endif
21805
21806 SET_TEXT_POS_FROM_MARKER (start, w->start);
21807
21808
21809
21810 if (MINI_WINDOW_P (w))
21811 GIVE_UP (1);
21812
21813
21814 if (windows_or_buffers_changed || f->cursor_type_changed)
21815 GIVE_UP (2);
21816
21817
21818
21819
21820 if (w->last_overlay_modified != OVERLAY_MODIFF)
21821 GIVE_UP (200);
21822
21823
21824
21825
21826
21827 if (current_buffer->clip_changed
21828 || current_buffer->prevent_redisplay_optimizations_p)
21829 GIVE_UP (3);
21830
21831
21832 if (!FRAME_WINDOW_P (f)
21833 && (!FRAME_LINE_INS_DEL_OK (f)
21834 || !WINDOW_FULL_WIDTH_P (w)))
21835 GIVE_UP (4);
21836
21837
21838 if (PT < CHARPOS (start))
21839 GIVE_UP (5);
21840
21841
21842 if (w->last_modified == 0)
21843 GIVE_UP (6);
21844
21845
21846 if (w->hscroll != 0)
21847 GIVE_UP (7);
21848
21849
21850 if (!w->window_end_valid)
21851 GIVE_UP (8);
21852
21853
21854 if (!NILP (Vshow_trailing_whitespace))
21855 GIVE_UP (11);
21856
21857
21858
21859 if (overlay_arrows_changed_p (false))
21860 GIVE_UP (12);
21861
21862
21863
21864
21865
21866 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21867 GIVE_UP (21);
21868
21869
21870
21871
21872
21873
21874
21875
21876
21877 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21878 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21879 GIVE_UP (22);
21880
21881
21882
21883 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21884 GIVE_UP (23);
21885
21886
21887
21888 if (EQ (Vdisplay_line_numbers, Qrelative)
21889 || EQ (Vdisplay_line_numbers, Qvisual)
21890 || (!NILP (Vdisplay_line_numbers)
21891 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21892 Qline_number_current_line,
21893 w->frame))))
21894 GIVE_UP (24);
21895
21896
21897
21898
21899 if (composition_break_at_point)
21900 GIVE_UP (27);
21901
21902
21903
21904
21905
21906 if (MODIFF > SAVE_MODIFF
21907
21908 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21909 {
21910 if (GPT - BEG < BEG_UNCHANGED)
21911 BEG_UNCHANGED = GPT - BEG;
21912 if (Z - GPT < END_UNCHANGED)
21913 END_UNCHANGED = Z - GPT;
21914 }
21915
21916
21917 first_changed_charpos = BEG + BEG_UNCHANGED;
21918 last_changed_charpos = Z - END_UNCHANGED;
21919
21920
21921
21922
21923
21924
21925 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21926 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21927 && ((last_changed_charpos < CHARPOS (start)
21928 && CHARPOS (start) == BEGV)
21929 || (last_changed_charpos < CHARPOS (start) - 1
21930 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21931 {
21932 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21933 struct glyph_row *r0;
21934
21935
21936
21937 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21938 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21939 Z_delta = Z - Z_old;
21940 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21941
21942
21943
21944
21945 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21946 GIVE_UP (13);
21947
21948
21949
21950
21951 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21952 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21953 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21954
21955 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21956 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21957 {
21958
21959 if (Z_delta || Z_delta_bytes)
21960 {
21961 struct glyph_row *r1
21962 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21963 increment_matrix_positions (w->current_matrix,
21964 MATRIX_ROW_VPOS (r0, current_matrix),
21965 MATRIX_ROW_VPOS (r1, current_matrix),
21966 Z_delta, Z_delta_bytes);
21967 }
21968
21969
21970 row = row_containing_pos (w, PT, r0, NULL, 0);
21971 if (row)
21972 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21973 return 1;
21974 }
21975 }
21976
21977
21978
21979
21980
21981 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
21982
21983
21984 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
21985 || first_changed_charpos == last_changed_charpos))
21986 {
21987 struct glyph_row *r0;
21988
21989
21990
21991
21992 if (PT >= MATRIX_ROW_END_CHARPOS (row))
21993 GIVE_UP (14);
21994
21995
21996
21997
21998 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21999 if (TEXT_POS_EQUAL_P (start, r0->minpos)
22000
22001 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
22002 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
22003 {
22004
22005
22006 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22007 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22008
22009
22010 row = row_containing_pos (w, PT, r0, NULL, 0);
22011 if (row)
22012 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22013 return 2;
22014 }
22015 }
22016
22017
22018
22019
22020
22021
22022
22023
22024 if (CHARPOS (start) >= first_changed_charpos
22025 && CHARPOS (start) <= last_changed_charpos)
22026 GIVE_UP (15);
22027
22028
22029
22030
22031
22032 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
22033 if (!TEXT_POS_EQUAL_P (start, row->minpos))
22034 GIVE_UP (16);
22035
22036
22037
22038 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
22039 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
22040 GIVE_UP (20);
22041
22042
22043
22044
22045
22046 #ifdef HAVE_NTGUI
22047 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
22048 GIVE_UP (25);
22049 #endif
22050
22051
22052
22053
22054
22055
22056
22057 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
22058 if (last_unchanged_at_beg_row)
22059 {
22060
22061
22062
22063
22064 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
22065 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
22066 && last_unchanged_at_beg_row > w->current_matrix->rows)
22067 --last_unchanged_at_beg_row;
22068
22069 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
22070 GIVE_UP (17);
22071
22072 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
22073 GIVE_UP (18);
22074
22075
22076
22077 if (it.sp > 1
22078 && it.method == GET_FROM_IMAGE && it.image_id == -1)
22079 GIVE_UP (26);
22080 start_pos = it.current.pos;
22081
22082
22083
22084
22085 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
22086 current_matrix);
22087 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22088 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
22089
22090 eassert (it.hpos == 0 && it.current_x == 0);
22091 }
22092 else
22093 {
22094
22095
22096 start_display (&it, w, start);
22097 it.vpos = it.first_vpos;
22098 start_pos = it.current.pos;
22099 }
22100
22101
22102
22103
22104
22105
22106
22107 first_unchanged_at_end_row
22108 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
22109 IF_DEBUG (debug_delta = delta);
22110 IF_DEBUG (debug_delta_bytes = delta_bytes);
22111
22112
22113
22114
22115
22116
22117 stop_pos = 0;
22118 if (first_unchanged_at_end_row)
22119 {
22120 eassert (last_unchanged_at_beg_row == NULL
22121 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
22122
22123
22124
22125
22126
22127 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
22128 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22129 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22130 < it.last_visible_y))
22131 ++first_unchanged_at_end_row;
22132
22133 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22134 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22135 >= it.last_visible_y))
22136 first_unchanged_at_end_row = NULL;
22137 else
22138 {
22139 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
22140 + delta);
22141 first_unchanged_at_end_vpos
22142 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
22143 eassert (stop_pos >= Z - END_UNCHANGED);
22144 }
22145 }
22146 else if (last_unchanged_at_beg_row == NULL)
22147 GIVE_UP (19);
22148
22149
22150 #ifdef GLYPH_DEBUG
22151
22152
22153
22154
22155 eassert (first_unchanged_at_end_row == NULL
22156 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22157
22158 debug_last_unchanged_at_beg_vpos
22159 = (last_unchanged_at_beg_row
22160 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
22161 : -1);
22162 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
22163
22164 #endif
22165
22166
22167
22168
22169
22170 w->cursor.vpos = -1;
22171 last_text_row = NULL;
22172 overlay_arrow_seen = false;
22173 if (it.current_y < it.last_visible_y
22174 && !f->fonts_changed
22175 && (first_unchanged_at_end_row == NULL
22176 || IT_CHARPOS (it) < stop_pos))
22177 it.glyph_row->reversed_p = false;
22178 while (it.current_y < it.last_visible_y
22179 && !f->fonts_changed
22180 && (first_unchanged_at_end_row == NULL
22181 || IT_CHARPOS (it) < stop_pos))
22182 {
22183 if (display_line (&it, -1))
22184 last_text_row = it.glyph_row - 1;
22185 }
22186
22187 if (f->fonts_changed)
22188 return -1;
22189
22190
22191
22192
22193
22194
22195
22196
22197
22198
22199
22200 if (!w->window_end_valid)
22201 {
22202 clear_glyph_matrix (w->desired_matrix);
22203 return -1;
22204 }
22205
22206
22207
22208
22209 if (first_unchanged_at_end_row
22210
22211
22212 && it.current_y < it.last_visible_y)
22213 {
22214 dvpos = (it.vpos
22215 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22216 current_matrix));
22217 dy = it.current_y - first_unchanged_at_end_row->y;
22218 run.current_y = first_unchanged_at_end_row->y;
22219 run.desired_y = run.current_y + dy;
22220 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22221 }
22222 else
22223 {
22224 delta = delta_bytes = dvpos = dy
22225 = run.current_y = run.desired_y = run.height = 0;
22226 first_unchanged_at_end_row = NULL;
22227 }
22228 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22229
22230
22231
22232
22233
22234
22235
22236
22237
22238
22239 if (w->cursor.vpos < 0)
22240 {
22241
22242 if (PT < CHARPOS (start_pos)
22243 && last_unchanged_at_beg_row)
22244 {
22245 row = row_containing_pos (w, PT,
22246 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22247 last_unchanged_at_beg_row + 1, 0);
22248 if (row)
22249 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22250 }
22251
22252
22253 else if (first_unchanged_at_end_row)
22254 {
22255 row = row_containing_pos (w, PT - delta,
22256 first_unchanged_at_end_row, NULL, 0);
22257 if (row)
22258 set_cursor_from_row (w, row, w->current_matrix, delta,
22259 delta_bytes, dy, dvpos);
22260 }
22261
22262
22263 if (w->cursor.vpos < 0)
22264 {
22265 clear_glyph_matrix (w->desired_matrix);
22266 return -1;
22267 }
22268 }
22269
22270
22271 {
22272 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22273 int bot_scroll_margin = top_scroll_margin;
22274 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22275
22276 if (window_wants_header_line (w))
22277 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22278 if (window_wants_tab_line (w))
22279 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22280
22281 if ((w->cursor.y < top_scroll_margin
22282 && CHARPOS (start) > BEGV)
22283
22284
22285 || (w->cursor.y
22286 + (cursor_row_fully_visible_p (w, false, true, true)
22287 ? 1
22288 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22289 {
22290 w->cursor.vpos = -1;
22291 clear_glyph_matrix (w->desired_matrix);
22292 return -1;
22293 }
22294 }
22295
22296
22297
22298
22299 if (dy && run.height)
22300 {
22301 update_begin (f);
22302
22303 if (FRAME_WINDOW_P (f))
22304 {
22305 #ifdef HAVE_WINDOW_SYSTEM
22306 gui_update_window_begin (w);
22307 FRAME_RIF (f)->clear_window_mouse_face (w);
22308 FRAME_RIF (f)->scroll_run_hook (w, &run);
22309 gui_update_window_end (w, false, false);
22310 #endif
22311 }
22312 else
22313 {
22314
22315
22316 int from_vpos
22317 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22318 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22319 int end = (WINDOW_TOP_EDGE_LINE (w)
22320 + window_wants_tab_line (w)
22321 + window_wants_header_line (w)
22322 + window_internal_height (w));
22323
22324 gui_clear_window_mouse_face (w);
22325
22326
22327 if (dvpos > 0)
22328 {
22329
22330
22331 set_terminal_window (f, end);
22332
22333
22334
22335 if (!FRAME_SCROLL_REGION_OK (f))
22336 ins_del_lines (f, end - dvpos, -dvpos);
22337
22338
22339
22340 ins_del_lines (f, from, dvpos);
22341 }
22342 else if (dvpos < 0)
22343 {
22344
22345
22346 set_terminal_window (f, end);
22347
22348
22349
22350
22351
22352 ins_del_lines (f, from + dvpos, dvpos);
22353
22354
22355
22356 if (!FRAME_SCROLL_REGION_OK (f))
22357 ins_del_lines (f, end + dvpos, -dvpos);
22358 }
22359
22360 set_terminal_window (f, 0);
22361 }
22362
22363 update_end (f);
22364 }
22365
22366
22367
22368
22369 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22370 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22371 if (dvpos < 0)
22372 {
22373 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22374 bottom_vpos, dvpos);
22375 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22376 bottom_vpos);
22377 }
22378 else if (dvpos > 0)
22379 {
22380 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22381 bottom_vpos, dvpos);
22382 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22383 first_unchanged_at_end_vpos + dvpos);
22384 }
22385
22386
22387
22388 if (!FRAME_WINDOW_P (f))
22389 sync_frame_with_window_matrix_rows (w);
22390
22391
22392 if (delta || delta_bytes)
22393 increment_matrix_positions (current_matrix,
22394 first_unchanged_at_end_vpos + dvpos,
22395 bottom_vpos, delta, delta_bytes);
22396
22397
22398 if (dy)
22399 shift_glyph_matrix (w, current_matrix,
22400 first_unchanged_at_end_vpos + dvpos,
22401 bottom_vpos, dy);
22402
22403 if (first_unchanged_at_end_row)
22404 {
22405 first_unchanged_at_end_row += dvpos;
22406 if (first_unchanged_at_end_row->y >= it.last_visible_y
22407 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22408 first_unchanged_at_end_row = NULL;
22409 }
22410
22411
22412
22413 last_text_row_at_end = NULL;
22414 if (dy < 0)
22415 {
22416
22417
22418
22419
22420
22421 int last_vpos = w->window_end_vpos + dvpos;
22422 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22423
22424
22425 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22426
22427
22428
22429
22430 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22431 {
22432 init_to_row_start (&it, w, last_row);
22433 it.vpos = last_vpos;
22434 it.current_y = last_row->y;
22435 }
22436 else
22437 {
22438 init_to_row_end (&it, w, last_row);
22439 it.vpos = 1 + last_vpos;
22440 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22441 ++last_row;
22442 }
22443
22444
22445
22446 it.continuation_lines_width = last_row->continuation_lines_width;
22447 it.hpos = it.current_x = 0;
22448
22449
22450 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22451 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22452 {
22453
22454
22455
22456
22457 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22458 if (display_line (&it, w->cursor.vpos))
22459 last_text_row_at_end = it.glyph_row - 1;
22460 }
22461 }
22462
22463
22464 if (first_unchanged_at_end_row && !last_text_row_at_end)
22465 {
22466
22467
22468
22469
22470 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22471 row = find_last_row_displaying_text (w->current_matrix, &it,
22472 first_unchanged_at_end_row);
22473 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22474 adjust_window_ends (w, row, true);
22475 eassert (w->window_end_bytepos >= 0);
22476 IF_DEBUG (debug_method_add (w, "A"));
22477 }
22478 else if (last_text_row_at_end)
22479 {
22480 adjust_window_ends (w, last_text_row_at_end, false);
22481 eassert (w->window_end_bytepos >= 0);
22482 IF_DEBUG (debug_method_add (w, "B"));
22483 }
22484 else if (last_text_row)
22485 {
22486
22487
22488
22489 adjust_window_ends (w, last_text_row, false);
22490 eassert (w->window_end_bytepos >= 0);
22491 }
22492 else if (first_unchanged_at_end_row == NULL
22493 && last_text_row == NULL
22494 && last_text_row_at_end == NULL)
22495 {
22496
22497
22498 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22499 int vpos = w->window_end_vpos;
22500 struct glyph_row *current_row = current_matrix->rows + vpos;
22501 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22502
22503 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22504 {
22505 eassert (first_vpos <= vpos);
22506 if (desired_row->enabled_p)
22507 {
22508 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22509 row = desired_row;
22510 }
22511 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22512 row = current_row;
22513 }
22514
22515 w->window_end_vpos = vpos + 1;
22516 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22517 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22518 eassert (w->window_end_bytepos >= 0);
22519 IF_DEBUG (debug_method_add (w, "C"));
22520 }
22521 else
22522 emacs_abort ();
22523
22524 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22525 debug_end_vpos = w->window_end_vpos));
22526
22527
22528 w->window_end_valid = false;
22529 w->desired_matrix->no_scrolling_p = true;
22530 return 3;
22531
22532 #undef GIVE_UP
22533 }
22534
22535
22536
22537
22538
22539
22540
22541 #ifdef GLYPH_DEBUG
22542
22543 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22544 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22545 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22546
22547
22548
22549
22550
22551
22552
22553
22554 void
22555 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22556 {
22557 int i;
22558 for (i = 0; i < matrix->nrows; ++i)
22559 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22560 }
22561
22562
22563
22564
22565
22566 void
22567 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22568 {
22569 if (glyph->type == CHAR_GLYPH
22570 || glyph->type == GLYPHLESS_GLYPH)
22571 {
22572 fprintf (stderr,
22573 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22574 glyph - row->glyphs[TEXT_AREA],
22575 (glyph->type == CHAR_GLYPH
22576 ? 'C'
22577 : 'G'),
22578 glyph->charpos,
22579 (BUFFERP (glyph->object)
22580 ? 'B'
22581 : (STRINGP (glyph->object)
22582 ? 'S'
22583 : (NILP (glyph->object)
22584 ? '0'
22585 : '-'))),
22586 glyph->pixel_width,
22587 glyph->u.ch,
22588 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22589 ? (int) glyph->u.ch
22590 : '.'),
22591 glyph->face_id,
22592 glyph->left_box_line_p,
22593 glyph->right_box_line_p);
22594 }
22595 else if (glyph->type == STRETCH_GLYPH)
22596 {
22597 fprintf (stderr,
22598 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22599 glyph - row->glyphs[TEXT_AREA],
22600 'S',
22601 glyph->charpos,
22602 (BUFFERP (glyph->object)
22603 ? 'B'
22604 : (STRINGP (glyph->object)
22605 ? 'S'
22606 : (NILP (glyph->object)
22607 ? '0'
22608 : '-'))),
22609 glyph->pixel_width,
22610 0u,
22611 ' ',
22612 glyph->face_id,
22613 glyph->left_box_line_p,
22614 glyph->right_box_line_p);
22615 }
22616 else if (glyph->type == IMAGE_GLYPH)
22617 {
22618 fprintf (stderr,
22619 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22620 glyph - row->glyphs[TEXT_AREA],
22621 'I',
22622 glyph->charpos,
22623 (BUFFERP (glyph->object)
22624 ? 'B'
22625 : (STRINGP (glyph->object)
22626 ? 'S'
22627 : (NILP (glyph->object)
22628 ? '0'
22629 : '-'))),
22630 glyph->pixel_width,
22631 (unsigned int) glyph->u.img_id,
22632 '.',
22633 glyph->face_id,
22634 glyph->left_box_line_p,
22635 glyph->right_box_line_p);
22636 }
22637 else if (glyph->type == COMPOSITE_GLYPH)
22638 {
22639 fprintf (stderr,
22640 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22641 glyph - row->glyphs[TEXT_AREA],
22642 '+',
22643 glyph->charpos,
22644 (BUFFERP (glyph->object)
22645 ? 'B'
22646 : (STRINGP (glyph->object)
22647 ? 'S'
22648 : (NILP (glyph->object)
22649 ? '0'
22650 : '-'))),
22651 glyph->pixel_width,
22652 (unsigned int) glyph->u.cmp.id);
22653 if (glyph->u.cmp.automatic)
22654 fprintf (stderr,
22655 "[%d-%d]",
22656 glyph->slice.cmp.from, glyph->slice.cmp.to);
22657 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22658 glyph->face_id,
22659 glyph->left_box_line_p,
22660 glyph->right_box_line_p);
22661 }
22662 else if (glyph->type == XWIDGET_GLYPH)
22663 {
22664 #ifndef HAVE_XWIDGETS
22665 eassume (false);
22666 #else
22667 fprintf (stderr,
22668 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22669 glyph - row->glyphs[TEXT_AREA],
22670 'X',
22671 glyph->charpos,
22672 (BUFFERP (glyph->object)
22673 ? 'B'
22674 : (STRINGP (glyph->object)
22675 ? 'S'
22676 : '-')),
22677 glyph->pixel_width,
22678 glyph->u.xwidget,
22679 '.',
22680 glyph->face_id,
22681 glyph->left_box_line_p,
22682 glyph->right_box_line_p);
22683 #endif
22684 }
22685 }
22686
22687
22688
22689
22690
22691
22692
22693 void
22694 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22695 {
22696 if (glyphs != 1)
22697 {
22698 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22699 "==============================================================================\n"),
22700 stderr);
22701 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22702 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22703 vpos,
22704 MATRIX_ROW_START_CHARPOS (row),
22705 MATRIX_ROW_END_CHARPOS (row),
22706 row->used[TEXT_AREA],
22707 row->contains_overlapping_glyphs_p,
22708 row->enabled_p,
22709 row->truncated_on_left_p,
22710 row->truncated_on_right_p,
22711 row->continued_p,
22712 MATRIX_ROW_CONTINUATION_LINE_P (row),
22713 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22714 row->ends_at_zv_p,
22715 row->fill_line_p,
22716 row->ends_in_middle_of_char_p,
22717 row->starts_in_middle_of_char_p,
22718 row->mouse_face_p,
22719 row->x,
22720 row->y,
22721 row->pixel_width,
22722 row->height,
22723 row->visible_height,
22724 row->ascent,
22725 row->phys_ascent);
22726
22727 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22728 row->end.overlay_string_index,
22729 row->continuation_lines_width);
22730 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22731 CHARPOS (row->start.string_pos),
22732 CHARPOS (row->end.string_pos));
22733 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22734 row->end.dpvec_index);
22735 }
22736
22737 if (glyphs > 1)
22738 {
22739 int area;
22740
22741 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22742 {
22743 struct glyph *glyph = row->glyphs[area];
22744 struct glyph *glyph_end = glyph + row->used[area];
22745
22746
22747 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22748 ++glyph_end;
22749
22750 if (glyph < glyph_end)
22751 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22752 stderr);
22753
22754 for (; glyph < glyph_end; ++glyph)
22755 dump_glyph (row, glyph, area);
22756 }
22757 }
22758 else if (glyphs == 1)
22759 {
22760 int area;
22761 char s[SHRT_MAX + 4];
22762
22763 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22764 {
22765 int i;
22766
22767 for (i = 0; i < row->used[area]; ++i)
22768 {
22769 struct glyph *glyph = row->glyphs[area] + i;
22770 if (i == row->used[area] - 1
22771 && area == TEXT_AREA
22772 && NILP (glyph->object)
22773 && glyph->type == CHAR_GLYPH
22774 && glyph->u.ch == ' ')
22775 {
22776 strcpy (&s[i], "[\\n]");
22777 i += 4;
22778 }
22779 else if (glyph->type == CHAR_GLYPH
22780 && glyph->u.ch < 0x80
22781 && glyph->u.ch >= ' ')
22782 s[i] = glyph->u.ch;
22783 else
22784 s[i] = '.';
22785 }
22786
22787 s[i] = '\0';
22788 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22789 }
22790 }
22791 }
22792
22793
22794 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22795 Sdump_glyph_matrix, 0, 1, "p",
22796 doc:
22797
22798
22799
22800
22801
22802 )
22803 (Lisp_Object glyphs)
22804 {
22805 struct window *w = XWINDOW (selected_window);
22806 struct buffer *buffer = XBUFFER (w->contents);
22807
22808 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22809 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22810 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22811 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22812 fputs ("=============================================\n", stderr);
22813 dump_glyph_matrix (w->current_matrix,
22814 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22815 return Qnil;
22816 }
22817
22818
22819 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22820 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22821 )
22822 (void)
22823 {
22824 struct frame *f = XFRAME (selected_frame);
22825
22826 if (f->current_matrix)
22827 dump_glyph_matrix (f->current_matrix, 1);
22828 else
22829 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22830 return Qnil;
22831 }
22832
22833
22834 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22835 doc:
22836
22837
22838
22839
22840 )
22841 (Lisp_Object row, Lisp_Object glyphs)
22842 {
22843 struct glyph_matrix *matrix;
22844 EMACS_INT vpos;
22845
22846 if (NILP (row))
22847 {
22848 int d1, d2, d3, d4, d5, ypos;
22849 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22850 &d1, &d2, &d3, &d4, &d5, &ypos);
22851 if (visible_p)
22852 vpos = ypos;
22853 else
22854 vpos = 0;
22855 }
22856 else
22857 {
22858 CHECK_FIXNUM (row);
22859 vpos = XFIXNUM (row);
22860 }
22861 matrix = XWINDOW (selected_window)->current_matrix;
22862 if (vpos >= 0 && vpos < matrix->nrows)
22863 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22864 vpos,
22865 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22866 return Qnil;
22867 }
22868
22869
22870 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22871 doc:
22872
22873
22874
22875
22876
22877
22878 )
22879 (Lisp_Object row, Lisp_Object glyphs)
22880 {
22881 #if defined (HAVE_WINDOW_SYSTEM)
22882 struct frame *sf = SELECTED_FRAME ();
22883 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22884 ? XWINDOW (sf->tab_bar_window)->current_matrix
22885 : sf->current_matrix;
22886 EMACS_INT vpos;
22887
22888 if (NILP (row))
22889 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22890 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22891 else
22892 {
22893 CHECK_FIXNUM (row);
22894 vpos = XFIXNUM (row);
22895 }
22896 if (vpos >= 0 && vpos < m->nrows)
22897 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22898 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22899 #endif
22900 return Qnil;
22901 }
22902
22903 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22904 doc:
22905
22906
22907
22908
22909
22910
22911 )
22912 (Lisp_Object row, Lisp_Object glyphs)
22913 {
22914 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22915 struct frame *sf = SELECTED_FRAME ();
22916 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22917 EMACS_INT vpos;
22918
22919 if (NILP (row))
22920 vpos = 0;
22921 else
22922 {
22923 CHECK_FIXNUM (row);
22924 vpos = XFIXNUM (row);
22925 }
22926 if (vpos >= 0 && vpos < m->nrows)
22927 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22928 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22929 #endif
22930 return Qnil;
22931 }
22932
22933
22934 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22935 doc:
22936 )
22937 (Lisp_Object arg)
22938 {
22939 if (NILP (arg))
22940 trace_redisplay_p = !trace_redisplay_p;
22941 else
22942 {
22943 arg = Fprefix_numeric_value (arg);
22944 trace_redisplay_p = XFIXNUM (arg) > 0;
22945 }
22946
22947 return Qnil;
22948 }
22949
22950
22951 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22952 doc:
22953 )
22954 (ptrdiff_t nargs, Lisp_Object *args)
22955 {
22956 Lisp_Object s = Fformat (nargs, args);
22957 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22958 return Qnil;
22959 }
22960
22961 #endif
22962
22963
22964
22965
22966
22967
22968
22969
22970
22971
22972
22973 static struct glyph_row *
22974 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
22975 {
22976 struct frame *f = XFRAME (WINDOW_FRAME (w));
22977 struct buffer *buffer = XBUFFER (w->contents);
22978 struct buffer *old = current_buffer;
22979 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
22980 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
22981 const unsigned char *arrow_end = arrow_string + arrow_len;
22982 const unsigned char *p;
22983 struct it it;
22984 bool multibyte_p;
22985 int n_glyphs_before;
22986
22987 set_buffer_temp (buffer);
22988 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
22989 scratch_glyph_row.reversed_p = false;
22990 it.glyph_row->used[TEXT_AREA] = 0;
22991 SET_TEXT_POS (it.position, 0, 0);
22992
22993 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
22994 p = arrow_string;
22995 while (p < arrow_end)
22996 {
22997 Lisp_Object face, ilisp;
22998
22999
23000 if (multibyte_p)
23001 it.c = it.char_to_display = check_char_and_length (p, &it.len);
23002 else
23003 {
23004 it.c = it.char_to_display = *p, it.len = 1;
23005 if (! ASCII_CHAR_P (it.c))
23006 it.char_to_display = BYTE8_TO_CHAR (it.c);
23007 }
23008 p += it.len;
23009
23010
23011 ilisp = make_fixnum (char_num++);
23012 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
23013 it.face_id = compute_char_face (f, it.char_to_display, face);
23014
23015
23016 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
23017 SET_TEXT_POS (it.position, -1, -1);
23018 PRODUCE_GLYPHS (&it);
23019
23020
23021
23022 if (it.current_x > it.last_visible_x)
23023 {
23024 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
23025 break;
23026 }
23027 }
23028
23029 set_buffer_temp (old);
23030 return it.glyph_row;
23031 }
23032
23033
23034
23035
23036
23037 static void
23038 insert_left_trunc_glyphs (struct it *it)
23039 {
23040 struct it truncate_it;
23041 struct glyph *from, *end, *to, *toend;
23042
23043 eassert (!FRAME_WINDOW_P (it->f)
23044 || (!it->glyph_row->reversed_p
23045 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23046 || (it->glyph_row->reversed_p
23047 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
23048
23049
23050 truncate_it = *it;
23051 truncate_it.current_x = 0;
23052 truncate_it.face_id = DEFAULT_FACE_ID;
23053 truncate_it.glyph_row = &scratch_glyph_row;
23054 truncate_it.area = TEXT_AREA;
23055 truncate_it.glyph_row->used[TEXT_AREA] = 0;
23056 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
23057 truncate_it.object = Qnil;
23058 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
23059
23060
23061 if (!it->glyph_row->reversed_p)
23062 {
23063 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23064
23065 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23066 end = from + tused;
23067 to = it->glyph_row->glyphs[TEXT_AREA];
23068 toend = to + it->glyph_row->used[TEXT_AREA];
23069 if (FRAME_WINDOW_P (it->f))
23070 {
23071
23072
23073
23074
23075
23076
23077
23078 int w = 0;
23079 struct glyph *g = to;
23080 short used;
23081
23082
23083
23084
23085
23086
23087 it->glyph_row->x = 0;
23088 while (g < toend && w < it->truncation_pixel_width)
23089 {
23090 w += g->pixel_width;
23091 ++g;
23092 }
23093 if (g - to - tused > 0)
23094 {
23095 memmove (to + tused, g, (toend - g) * sizeof(*g));
23096 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
23097 }
23098 used = it->glyph_row->used[TEXT_AREA];
23099 if (it->glyph_row->truncated_on_right_p
23100 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
23101 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
23102 == STRETCH_GLYPH)
23103 {
23104 int extra = w - it->truncation_pixel_width;
23105
23106 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
23107 }
23108 }
23109
23110 while (from < end)
23111 *to++ = *from++;
23112
23113
23114 if (!FRAME_WINDOW_P (it->f))
23115 {
23116 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
23117 {
23118 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23119 while (from < end)
23120 *to++ = *from++;
23121 }
23122 }
23123
23124 if (to > toend)
23125 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
23126 }
23127 else
23128 {
23129 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23130
23131
23132
23133 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
23134 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23135 toend = it->glyph_row->glyphs[TEXT_AREA];
23136 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
23137 if (FRAME_WINDOW_P (it->f))
23138 {
23139 int w = 0;
23140 struct glyph *g = to;
23141
23142 while (g >= toend && w < it->truncation_pixel_width)
23143 {
23144 w += g->pixel_width;
23145 --g;
23146 }
23147 if (to - g - tused > 0)
23148 to = g + tused;
23149 if (it->glyph_row->truncated_on_right_p
23150 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
23151 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
23152 {
23153 int extra = w - it->truncation_pixel_width;
23154
23155 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
23156 }
23157 }
23158
23159 while (from >= end && to >= toend)
23160 *to-- = *from--;
23161 if (!FRAME_WINDOW_P (it->f))
23162 {
23163 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
23164 {
23165 from =
23166 truncate_it.glyph_row->glyphs[TEXT_AREA]
23167 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23168 while (from >= end && to >= toend)
23169 *to-- = *from--;
23170 }
23171 }
23172 if (from >= end)
23173 {
23174
23175
23176 int move_by = from - end + 1;
23177 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23178 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23179
23180 for ( ; g >= g0; g--)
23181 g[move_by] = *g;
23182 while (from >= end)
23183 *to-- = *from--;
23184 it->glyph_row->used[TEXT_AREA] += move_by;
23185 }
23186 }
23187 }
23188
23189
23190 unsigned
23191 row_hash (struct glyph_row *row)
23192 {
23193 int area, k;
23194 unsigned hashval = 0;
23195
23196 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23197 for (k = 0; k < row->used[area]; ++k)
23198 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23199 + row->glyphs[area][k].u.val
23200 + row->glyphs[area][k].face_id
23201 + row->glyphs[area][k].padding_p
23202 + (row->glyphs[area][k].type << 2));
23203
23204 return hashval;
23205 }
23206
23207
23208
23209
23210
23211
23212
23213
23214
23215
23216
23217
23218
23219
23220
23221
23222
23223
23224 static void
23225 compute_line_metrics (struct it *it)
23226 {
23227 struct glyph_row *row = it->glyph_row;
23228
23229 if (FRAME_WINDOW_P (it->f))
23230 {
23231 int i, min_y, max_y;
23232
23233
23234
23235
23236 if (row->height == 0)
23237 {
23238 if (it->max_ascent + it->max_descent == 0)
23239 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23240 row->ascent = it->max_ascent;
23241 row->height = it->max_ascent + it->max_descent;
23242 row->phys_ascent = it->max_phys_ascent;
23243 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23244 row->extra_line_spacing = it->max_extra_line_spacing;
23245 }
23246
23247
23248 row->pixel_width = row->x;
23249 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23250 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23251
23252 eassert (row->pixel_width >= 0);
23253 eassert (row->ascent >= 0 && row->height > 0);
23254
23255 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23256 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23257
23258
23259
23260
23261 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23262 && row->phys_ascent > row->ascent)
23263 {
23264 row->height += row->phys_ascent - row->ascent;
23265 row->ascent = row->phys_ascent;
23266 }
23267
23268
23269 row->visible_height = row->height;
23270
23271 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23272 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23273
23274 if (row->y < min_y)
23275 row->visible_height -= min_y - row->y;
23276 if (row->y + row->height > max_y)
23277 row->visible_height -= row->y + row->height - max_y;
23278 }
23279 else
23280 {
23281 row->pixel_width = row->used[TEXT_AREA];
23282 if (row->continued_p)
23283 row->pixel_width -= it->continuation_pixel_width;
23284 else if (row->truncated_on_right_p)
23285 row->pixel_width -= it->truncation_pixel_width;
23286 row->ascent = row->phys_ascent = 0;
23287 row->height = row->phys_height = row->visible_height = 1;
23288 row->extra_line_spacing = 0;
23289 }
23290
23291
23292 row->hash = row_hash (row);
23293
23294 it->max_ascent = it->max_descent = 0;
23295 it->max_phys_ascent = it->max_phys_descent = 0;
23296 }
23297
23298
23299 static void
23300 clear_position (struct it *it)
23301 {
23302 it->position.charpos = 0;
23303 it->position.bytepos = 0;
23304 }
23305
23306
23307
23308
23309
23310
23311
23312
23313
23314
23315
23316
23317
23318 static bool
23319 append_space_for_newline (struct it *it, bool default_face_p)
23320 {
23321 int n = it->glyph_row->used[TEXT_AREA];
23322
23323 if (it->glyph_row->glyphs[TEXT_AREA] + n
23324 < it->glyph_row->glyphs[1 + TEXT_AREA])
23325 {
23326
23327
23328
23329
23330 enum display_element_type saved_what = it->what;
23331 int saved_c = it->c, saved_len = it->len;
23332 int saved_char_to_display = it->char_to_display;
23333 int saved_x = it->current_x;
23334 const int saved_face_id = it->face_id;
23335 bool saved_box_end = it->end_of_box_run_p;
23336 struct text_pos saved_pos = it->position;
23337 Lisp_Object saved_object = it->object;
23338 struct face *face;
23339
23340 it->what = IT_CHARACTER;
23341 clear_position (it);
23342 it->object = Qnil;
23343 it->len = 1;
23344
23345 int char_width = 1;
23346
23347 if (default_face_p
23348 #ifdef HAVE_WINDOW_SYSTEM
23349 || FRAME_WINDOW_P (it->f)
23350 #endif
23351 )
23352 {
23353 const int local_default_face_id =
23354 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23355
23356 #ifdef HAVE_WINDOW_SYSTEM
23357 if (FRAME_WINDOW_P (it->f))
23358 {
23359 struct face *default_face
23360 = FACE_FROM_ID (it->f, local_default_face_id);
23361 struct font *font = (default_face->font
23362 ? default_face->font
23363 : FRAME_FONT (it->f));
23364 char_width = (font->average_width
23365 ? font->average_width
23366 : font->space_width);
23367 }
23368 #endif
23369 if (default_face_p)
23370 it->face_id = local_default_face_id;
23371 }
23372
23373
23374
23375
23376 const int indicator_column =
23377 fill_column_indicator_column (it, char_width);
23378 int saved_end_of_box_run = it->end_of_box_run_p;
23379 bool should_keep_end_of_box_run = false;
23380
23381 if (it->current_x == indicator_column)
23382 {
23383 it->c = it->char_to_display
23384 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23385 it->face_id
23386 = merge_faces (it->w, Qfill_column_indicator,
23387 0, saved_face_id);
23388 face = FACE_FROM_ID (it->f, it->face_id);
23389 }
23390 else
23391 {
23392 it->c = it->char_to_display = ' ';
23393
23394
23395
23396 face = FACE_FROM_ID (it->f, it->face_id);
23397 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23398
23399
23400
23401
23402 if (!(it->glyph_row->reversed_p
23403
23404
23405
23406 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23407 should_keep_end_of_box_run = true;
23408 }
23409 PRODUCE_GLYPHS (it);
23410
23411
23412 if (should_keep_end_of_box_run)
23413 it->end_of_box_run_p = saved_end_of_box_run;
23414 #ifdef HAVE_WINDOW_SYSTEM
23415 if (FRAME_WINDOW_P (it->f))
23416 {
23417
23418
23419
23420 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23421 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23422 if (n == 0)
23423 {
23424 Lisp_Object height, total_height;
23425 int extra_line_spacing = it->extra_line_spacing;
23426 int boff = font->baseline_offset;
23427
23428 if (font->vertical_centering)
23429 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23430
23431 it->object = saved_object;
23432 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23433
23434
23435 height = get_it_property (it, Qline_height);
23436 if (CONSP (height)
23437 && CONSP (XCDR (height))
23438 && NILP (XCDR (XCDR (height))))
23439 {
23440 total_height = XCAR (XCDR (height));
23441 height = XCAR (height);
23442 }
23443 else
23444 total_height = Qnil;
23445 height = calc_line_height_property (it, height, font, boff, true);
23446
23447 if (it->override_ascent >= 0)
23448 {
23449 it->ascent = it->override_ascent;
23450 it->descent = it->override_descent;
23451 boff = it->override_boff;
23452 }
23453 if (EQ (height, Qt))
23454 extra_line_spacing = 0;
23455 else
23456 {
23457 Lisp_Object spacing;
23458
23459 it->phys_ascent = it->ascent;
23460 it->phys_descent = it->descent;
23461 if (!NILP (height)
23462 && XFIXNUM (height) > it->ascent + it->descent)
23463 it->ascent = XFIXNUM (height) - it->descent;
23464
23465 if (!NILP (total_height))
23466 spacing = calc_line_height_property (it, total_height, font,
23467 boff, false);
23468 else
23469 {
23470 spacing = get_it_property (it, Qline_spacing);
23471 spacing = calc_line_height_property (it, spacing, font,
23472 boff, false);
23473 }
23474 if (FIXNUMP (spacing))
23475 {
23476 extra_line_spacing = XFIXNUM (spacing);
23477 if (!NILP (total_height))
23478 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23479 }
23480 }
23481 if (extra_line_spacing > 0)
23482 {
23483 it->descent += extra_line_spacing;
23484 if (extra_line_spacing > it->max_extra_line_spacing)
23485 it->max_extra_line_spacing = extra_line_spacing;
23486 }
23487 it->max_ascent = it->ascent;
23488 it->max_descent = it->descent;
23489
23490 it->glyph_row->height = 0;
23491 }
23492
23493 g->ascent = it->max_ascent;
23494 g->descent = it->max_descent;
23495 }
23496 #endif
23497 it->override_ascent = -1;
23498 it->constrain_row_ascent_descent_p = false;
23499 it->current_x = saved_x;
23500 it->object = saved_object;
23501 it->position = saved_pos;
23502 it->what = saved_what;
23503 it->face_id = saved_face_id;
23504 it->len = saved_len;
23505 it->c = saved_c;
23506 it->char_to_display = saved_char_to_display;
23507 it->end_of_box_run_p = saved_box_end;
23508 return true;
23509 }
23510
23511 return false;
23512 }
23513
23514
23515
23516
23517
23518
23519
23520
23521
23522 static void
23523 extend_face_to_end_of_line (struct it *it)
23524 {
23525 struct frame *f = it->f;
23526
23527
23528
23529
23530
23531
23532 if ((it->current_x >= it->last_visible_x
23533 + (!FRAME_WINDOW_P (f)
23534 && it->glyph_row->reversed_p
23535 && !it->glyph_row->continued_p))
23536
23537
23538 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23539 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23540 return;
23541
23542 specpdl_ref count = SPECPDL_INDEX ();
23543
23544
23545
23546
23547 specbind (Qinhibit_quit, Qt);
23548
23549 struct face *default_face =
23550 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23551 if (!default_face)
23552 return;
23553
23554 const int extend_face_id =
23555 (it->face_id == default_face->id || it->s != NULL)
23556 ? it->face_id
23557 : (it->glyph_row->ends_at_zv_p
23558 ? default_face->id
23559 : face_at_pos (it, LFACE_EXTEND_INDEX));
23560 unbind_to (count, Qnil);
23561
23562
23563
23564
23565 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23566 ? it->saved_face_id
23567 : extend_face_id));
23568
23569 if (FRAME_WINDOW_P (f)
23570 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23571 && face->box == FACE_NO_BOX
23572 && face->underline == FACE_NO_UNDERLINE
23573 && !face->overline_p
23574 && !face->strike_through_p
23575 && face->background == FRAME_BACKGROUND_PIXEL (f)
23576 #ifdef HAVE_WINDOW_SYSTEM
23577 && !face->stipple
23578 #endif
23579 && !it->glyph_row->reversed_p
23580 && !display_fill_column_indicator)
23581 return;
23582
23583
23584
23585 it->glyph_row->fill_line_p = true;
23586
23587 const int orig_face_id = it->face_id;
23588
23589
23590
23591
23592
23593 if (!ASCII_CHAR_P (it->c))
23594 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23595
23596
23597 #ifdef HAVE_WINDOW_SYSTEM
23598 if (FRAME_WINDOW_P (f))
23599 {
23600
23601
23602 if (it->glyph_row->used[TEXT_AREA] == 0)
23603 {
23604 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23605 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23606 it->glyph_row->used[TEXT_AREA] = 1;
23607 }
23608
23609
23610 if (!(it->glyph_row->mode_line_p
23611 || (WINDOWP (f->tab_bar_window)
23612 && it->w == XWINDOW (f->tab_bar_window))
23613 #ifndef HAVE_EXT_TOOL_BAR
23614 || (WINDOWP (f->tool_bar_window)
23615 && it->w == XWINDOW (f->tool_bar_window))
23616 #endif
23617 ))
23618 {
23619 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23620 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23621 {
23622 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23623 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23624 default_face->id;
23625 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23626 }
23627 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23628 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23629 {
23630 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23631 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23632 default_face->id;
23633 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23634 }
23635
23636 struct font *font = (default_face->font
23637 ? default_face->font
23638 : FRAME_FONT (f));
23639
23640 const int char_width = (font->average_width
23641 ? font->average_width
23642 : font->space_width);
23643
23644 const int indicator_column =
23645 fill_column_indicator_column (it, char_width);
23646
23647 const char saved_char = it->char_to_display;
23648 const struct text_pos saved_pos = it->position;
23649 const bool saved_avoid_cursor = it->avoid_cursor_p;
23650 const bool saved_box_start = it->start_of_box_run_p;
23651 Lisp_Object save_object = it->object;
23652 const int saved_face_id = it->face_id;
23653
23654 it->face_id = extend_face_id;
23655 it->avoid_cursor_p = true;
23656 it->object = Qnil;
23657
23658 const int stretch_height = it->ascent + it->descent;
23659 const int stretch_ascent =
23660 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23661
23662 if (indicator_column >= 0
23663 && indicator_column > it->current_x
23664 && indicator_column < it->last_visible_x)
23665 {
23666
23667
23668
23669
23670 const int stretch_width =
23671 indicator_column - it->current_x - char_width;
23672
23673 clear_position (it);
23674
23675
23676
23677 if (stretch_width > 0)
23678 {
23679 append_stretch_glyph (it, Qnil, stretch_width,
23680 stretch_height, stretch_ascent);
23681 }
23682
23683
23684
23685 if (it->current_x < indicator_column)
23686 {
23687 const int save_face_id = it->face_id;
23688 const int save_ascent = it->ascent;
23689 const int save_descent = it->descent;
23690 it->char_to_display
23691 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23692 it->face_id
23693 = merge_faces (it->w, Qfill_column_indicator,
23694 0, extend_face_id);
23695 PRODUCE_GLYPHS (it);
23696 it->face_id = save_face_id;
23697 it->ascent = save_ascent;
23698 it->descent = save_descent;
23699 }
23700 }
23701
23702
23703
23704 if (!it->glyph_row->reversed_p)
23705 {
23706 const int stretch_width = it->last_visible_x - it->current_x;
23707
23708 if (stretch_width > 0)
23709 {
23710 clear_position (it);
23711 append_stretch_glyph (it, Qnil, stretch_width,
23712 stretch_height, stretch_ascent);
23713 }
23714 }
23715
23716 it->char_to_display = saved_char;
23717 it->position = saved_pos;
23718 it->avoid_cursor_p = saved_avoid_cursor;
23719 it->start_of_box_run_p = saved_box_start;
23720 it->object = save_object;
23721 it->face_id = saved_face_id;
23722 }
23723 if (it->glyph_row->reversed_p)
23724 {
23725
23726
23727
23728
23729
23730 struct font *font = face->font ? face->font : FRAME_FONT (f);
23731 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23732 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23733 struct glyph *g;
23734 int row_width, stretch_ascent, stretch_width;
23735 struct text_pos saved_pos;
23736 int saved_face_id;
23737 bool saved_avoid_cursor, saved_box_start;
23738
23739 for (row_width = 0, g = row_start; g < row_end; g++)
23740 row_width += g->pixel_width;
23741
23742
23743
23744
23745 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23746 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23747 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23748 stretch_width = window_box_width (it->w, TEXT_AREA);
23749 else
23750 stretch_width = it->last_visible_x - it->first_visible_x;
23751 stretch_width -= row_width;
23752
23753 if (stretch_width > 0)
23754 {
23755 stretch_ascent =
23756 (((it->ascent + it->descent)
23757 * FONT_BASE (font)) / FONT_HEIGHT (font));
23758 saved_pos = it->position;
23759 clear_position (it);
23760 saved_avoid_cursor = it->avoid_cursor_p;
23761 it->avoid_cursor_p = true;
23762 saved_face_id = it->face_id;
23763 saved_box_start = it->start_of_box_run_p;
23764
23765
23766
23767 it->face_id = (it->glyph_row->ends_at_zv_p ?
23768 default_face->id : face->id);
23769
23770 it->start_of_box_run_p = false;
23771 append_stretch_glyph (it, Qnil, stretch_width,
23772 it->ascent + it->descent, stretch_ascent);
23773 it->position = saved_pos;
23774 it->avoid_cursor_p = saved_avoid_cursor;
23775 it->face_id = saved_face_id;
23776 it->start_of_box_run_p = saved_box_start;
23777 }
23778
23779
23780
23781
23782 if (stretch_width < 0)
23783 it->glyph_row->x = stretch_width;
23784 }
23785 it->face_id = orig_face_id;
23786 }
23787 else
23788 #endif
23789 {
23790
23791 int saved_x = it->current_x;
23792 struct text_pos saved_pos = it->position;
23793 Lisp_Object saved_object = it->object;;
23794 enum display_element_type saved_what = it->what;
23795
23796 it->what = IT_CHARACTER;
23797 clear_position (it);
23798 it->object = Qnil;
23799 it->c = it->char_to_display = ' ';
23800 it->len = 1;
23801
23802 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23803 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23804 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23805 && !it->glyph_row->mode_line_p
23806 && face->background != FRAME_BACKGROUND_PIXEL (f))
23807 {
23808 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23809 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23810
23811 for (it->current_x = 0; g < e; g++)
23812 it->current_x += g->pixel_width;
23813
23814 it->area = LEFT_MARGIN_AREA;
23815 it->face_id = default_face->id;
23816 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23817 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23818 && g < it->glyph_row->glyphs[TEXT_AREA])
23819 {
23820 PRODUCE_GLYPHS (it);
23821
23822
23823 it->current_x += it->pixel_width;
23824 g++;
23825 }
23826
23827 it->current_x = saved_x;
23828 it->area = TEXT_AREA;
23829 }
23830
23831
23832
23833
23834 it->face_id = (it->glyph_row->ends_at_zv_p ?
23835 default_face->id : face->id);
23836
23837
23838
23839
23840
23841 it->current_x = it->glyph_row->used[TEXT_AREA];
23842
23843
23844
23845
23846
23847
23848
23849
23850 const int indicator_column =
23851 fill_column_indicator_column (it, 1) - it->first_visible_x;
23852
23853
23854 while (it->current_x <= it->last_visible_x)
23855 {
23856 if (it->current_x != indicator_column)
23857 PRODUCE_GLYPHS (it);
23858 else
23859 {
23860 int saved_face_id = it->face_id;
23861 it->face_id
23862 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23863 it->c = it->char_to_display
23864 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23865
23866 PRODUCE_GLYPHS (it);
23867
23868 it->face_id = saved_face_id;
23869 it->c = it->char_to_display = ' ';
23870 }
23871 }
23872
23873 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23874 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23875 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23876 && !it->glyph_row->mode_line_p
23877 && face->background != FRAME_BACKGROUND_PIXEL (f))
23878 {
23879 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23880 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23881
23882 for ( ; g < e; g++)
23883 it->current_x += g->pixel_width;
23884
23885 it->area = RIGHT_MARGIN_AREA;
23886 it->face_id = default_face->id;
23887 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23888 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23889 && g < it->glyph_row->glyphs[LAST_AREA])
23890 {
23891 PRODUCE_GLYPHS (it);
23892 it->current_x += it->pixel_width;
23893 g++;
23894 }
23895
23896 it->area = TEXT_AREA;
23897 }
23898
23899
23900
23901 it->current_x = saved_x;
23902 it->object = saved_object;
23903 it->position = saved_pos;
23904 it->what = saved_what;
23905 it->face_id = orig_face_id;
23906 }
23907 }
23908
23909
23910
23911
23912
23913 static bool
23914 trailing_whitespace_p (ptrdiff_t charpos)
23915 {
23916 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23917 int c = 0;
23918
23919 while (bytepos < ZV_BYTE
23920 && (c = FETCH_BYTE (bytepos),
23921 c == ' ' || c == '\t'))
23922 ++bytepos;
23923
23924 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23925 {
23926 if (bytepos != PT_BYTE)
23927 return true;
23928 }
23929 return false;
23930 }
23931
23932
23933
23934
23935 static void
23936 highlight_trailing_whitespace (struct it *it)
23937 {
23938 struct glyph_row *row = it->glyph_row;
23939 int used = row->used[TEXT_AREA];
23940
23941 if (used)
23942 {
23943 struct glyph *start = row->glyphs[TEXT_AREA];
23944 struct glyph *glyph = start + used - 1;
23945
23946 if (row->reversed_p)
23947 {
23948
23949
23950 glyph = start;
23951 start = row->glyphs[TEXT_AREA] + used - 1;
23952 }
23953
23954
23955
23956
23957
23958 if (!row->reversed_p)
23959 {
23960 while (glyph >= start
23961 && (glyph->type == CHAR_GLYPH
23962 || glyph->type == STRETCH_GLYPH)
23963 && NILP (glyph->object))
23964 --glyph;
23965 }
23966 else
23967 {
23968 while (glyph <= start
23969 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
23970 && NILP (glyph->object))
23971 ++glyph;
23972 }
23973
23974
23975
23976
23977 if ((row->reversed_p ? glyph <= start : glyph >= start)
23978 && BUFFERP (glyph->object)
23979 && (glyph->type == STRETCH_GLYPH
23980 || (glyph->type == CHAR_GLYPH
23981 && glyph->u.ch == ' '))
23982 && trailing_whitespace_p (glyph->charpos))
23983 {
23984 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
23985 if (face_id < 0)
23986 return;
23987
23988 if (!row->reversed_p)
23989 {
23990 while (glyph >= start
23991 && BUFFERP (glyph->object)
23992 && (glyph->type == STRETCH_GLYPH
23993 || (glyph->type == CHAR_GLYPH
23994 && glyph->u.ch == ' ')))
23995 (glyph--)->face_id = face_id;
23996 }
23997 else
23998 {
23999 while (glyph <= start
24000 && BUFFERP (glyph->object)
24001 && (glyph->type == STRETCH_GLYPH
24002 || (glyph->type == CHAR_GLYPH
24003 && glyph->u.ch == ' ')))
24004 (glyph++)->face_id = face_id;
24005 }
24006 }
24007 }
24008 }
24009
24010
24011
24012
24013
24014 static bool
24015 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
24016 {
24017 bool result = true;
24018
24019 if (charpos == CHARPOS (row->end.pos)
24020 || charpos == MATRIX_ROW_END_CHARPOS (row))
24021 {
24022
24023
24024
24025
24026
24027
24028
24029
24030 if (CHARPOS (row->end.string_pos) >= 0)
24031 {
24032 if (row->continued_p)
24033 result = true;
24034 else
24035 {
24036
24037 struct glyph *beg = row->glyphs[TEXT_AREA];
24038 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
24039 struct glyph *glyph;
24040
24041 result = false;
24042 for (glyph = end; glyph >= beg; --glyph)
24043 if (STRINGP (glyph->object))
24044 {
24045 Lisp_Object prop
24046 = Fget_char_property (make_fixnum (charpos),
24047 Qdisplay, Qnil);
24048 result =
24049 (!NILP (prop)
24050 && display_prop_string_p (prop, glyph->object));
24051
24052
24053
24054 if (!result)
24055 {
24056 Lisp_Object s = glyph->object;
24057
24058 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
24059 {
24060 ptrdiff_t gpos = glyph->charpos;
24061
24062 if (!NILP (Fget_char_property (make_fixnum (gpos),
24063 Qcursor, s)))
24064 {
24065 result = true;
24066 break;
24067 }
24068 }
24069 }
24070 break;
24071 }
24072 }
24073 }
24074 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
24075 {
24076
24077
24078
24079
24080 if (!row->ends_in_ellipsis_p)
24081 result = row->continued_p;
24082 else
24083
24084
24085
24086
24087 result = false;
24088 }
24089
24090
24091 else
24092 result = row->ends_at_zv_p;
24093 }
24094
24095 return result;
24096 }
24097
24098
24099
24100
24101 static bool
24102 cursor_row_p (struct glyph_row *row)
24103 {
24104 return row_for_charpos_p (row, PT);
24105 }
24106
24107
24108
24109
24110
24111
24112
24113
24114 static bool
24115 push_prefix_prop (struct it *it, Lisp_Object prop)
24116 {
24117 struct text_pos pos =
24118 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
24119
24120 eassert (it->method == GET_FROM_BUFFER
24121 || it->method == GET_FROM_DISPLAY_VECTOR
24122 || it->method == GET_FROM_STRING
24123 || it->method == GET_FROM_IMAGE);
24124
24125
24126
24127
24128
24129 push_it (it, &pos);
24130
24131 if (STRINGP (prop))
24132 {
24133 if (SCHARS (prop) == 0)
24134 {
24135 pop_it (it);
24136 return false;
24137 }
24138
24139 it->string = prop;
24140 it->string_from_prefix_prop_p = true;
24141 it->multibyte_p = STRING_MULTIBYTE (it->string);
24142 it->current.overlay_string_index = -1;
24143 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
24144 it->end_charpos = it->string_nchars = SCHARS (it->string);
24145 it->method = GET_FROM_STRING;
24146 it->stop_charpos = 0;
24147 it->prev_stop = 0;
24148 it->base_level_stop = 0;
24149 it->cmp_it.id = -1;
24150
24151
24152
24153 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
24154 it->paragraph_embedding = it->bidi_it.paragraph_dir;
24155 else
24156 it->paragraph_embedding = L2R;
24157
24158
24159 if (it->bidi_p)
24160 {
24161 it->bidi_it.string.lstring = it->string;
24162 it->bidi_it.string.s = NULL;
24163 it->bidi_it.string.schars = it->end_charpos;
24164 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
24165 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
24166 it->bidi_it.string.unibyte = !it->multibyte_p;
24167 it->bidi_it.w = it->w;
24168 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
24169 }
24170 }
24171 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24172 {
24173 it->method = GET_FROM_STRETCH;
24174 it->object = prop;
24175 }
24176 #ifdef HAVE_WINDOW_SYSTEM
24177 else if (IMAGEP (prop))
24178 {
24179 it->what = IT_IMAGE;
24180 it->image_id = lookup_image (it->f, prop, it->face_id);
24181 it->method = GET_FROM_IMAGE;
24182 }
24183 #endif
24184 else
24185 {
24186 pop_it (it);
24187 return false;
24188 }
24189
24190 return true;
24191 }
24192
24193
24194
24195 static Lisp_Object
24196 get_it_property (struct it *it, Lisp_Object prop)
24197 {
24198 Lisp_Object position, object = it->object;
24199
24200 if (STRINGP (object))
24201 position = make_fixnum (IT_STRING_CHARPOS (*it));
24202 else if (BUFFERP (object))
24203 {
24204 position = make_fixnum (IT_CHARPOS (*it));
24205 object = it->window;
24206 }
24207 else
24208 return Qnil;
24209
24210 return Fget_char_property (position, prop, object);
24211 }
24212
24213
24214
24215
24216 static Lisp_Object
24217 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24218 {
24219 Lisp_Object prefix = get_it_property (it, prop);
24220
24221
24222
24223 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24224 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24225 it->w->contents);
24226 return prefix;
24227 }
24228
24229
24230
24231 static void
24232 handle_line_prefix (struct it *it)
24233 {
24234 Lisp_Object prefix;
24235
24236 if (it->continuation_lines_width > 0)
24237 {
24238 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24239 if (NILP (prefix))
24240 prefix = Vwrap_prefix;
24241 }
24242 else
24243 {
24244 prefix = get_line_prefix_it_property (it, Qline_prefix);
24245 if (NILP (prefix))
24246 prefix = Vline_prefix;
24247 }
24248 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24249 {
24250
24251
24252
24253 it->line_wrap = TRUNCATE;
24254 it->avoid_cursor_p = true;
24255 }
24256 }
24257
24258
24259
24260
24261
24262
24263
24264 static void
24265 unproduce_glyphs (struct it *it, int n)
24266 {
24267 struct glyph *glyph, *end;
24268
24269 eassert (it->glyph_row);
24270 eassert (it->glyph_row->reversed_p);
24271 eassert (it->area == TEXT_AREA);
24272 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24273
24274 if (n > it->glyph_row->used[TEXT_AREA])
24275 n = it->glyph_row->used[TEXT_AREA];
24276 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24277 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24278 for ( ; glyph < end; glyph++)
24279 glyph[-n] = *glyph;
24280 }
24281
24282
24283
24284 static void
24285 find_row_edges (struct it *it, struct glyph_row *row,
24286 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24287 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24288 {
24289
24290
24291
24292
24293
24294 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24295 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24296 else
24297
24298
24299
24300 row->minpos = row->start.pos;
24301 if (max_pos <= 0)
24302 {
24303 max_pos = CHARPOS (it->current.pos);
24304 max_bpos = BYTEPOS (it->current.pos);
24305 }
24306
24307
24308
24309
24310
24311
24312
24313
24314
24315
24316
24317
24318
24319
24320
24321
24322
24323 if (row->ends_at_zv_p)
24324 row->maxpos = it->current.pos;
24325 else if (row->used[TEXT_AREA])
24326 {
24327 bool seen_this_string = false;
24328 struct glyph_row *r1 = row - 1;
24329
24330
24331 if (STRINGP (it->object)
24332
24333 && row > it->w->desired_matrix->rows
24334
24335 && !r1->mode_line_p
24336
24337 && r1->ends_in_newline_from_string_p)
24338 {
24339 struct glyph *start, *end;
24340
24341
24342
24343
24344
24345 if (!r1->reversed_p)
24346 {
24347 start = r1->glyphs[TEXT_AREA];
24348 end = start + r1->used[TEXT_AREA];
24349
24350 while (end > start
24351 && NILP ((end - 1)->object)
24352 && (end - 1)->charpos <= 0)
24353 --end;
24354 if (end > start)
24355 {
24356 if (EQ ((end - 1)->object, it->object))
24357 seen_this_string = true;
24358 }
24359 else
24360
24361
24362
24363
24364
24365 seen_this_string = true;
24366 }
24367 else
24368 {
24369 end = r1->glyphs[TEXT_AREA] - 1;
24370 start = end + r1->used[TEXT_AREA];
24371 while (end < start
24372 && NILP ((end + 1)->object)
24373 && (end + 1)->charpos <= 0)
24374 ++end;
24375 if (end < start)
24376 {
24377 if (EQ ((end + 1)->object, it->object))
24378 seen_this_string = true;
24379 }
24380 else
24381 seen_this_string = true;
24382 }
24383 }
24384
24385
24386
24387 if (row->ends_in_newline_from_string_p && !seen_this_string)
24388 {
24389
24390
24391
24392
24393
24394
24395
24396
24397 if (CHARPOS (row->end.pos) > max_pos)
24398 inc_both (&max_pos, &max_bpos);
24399 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24400 }
24401 else if (CHARPOS (it->eol_pos) > 0)
24402 SET_TEXT_POS (row->maxpos,
24403 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24404 else if (row->continued_p)
24405 {
24406
24407
24408
24409
24410
24411
24412 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24413 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24414 else
24415 {
24416 inc_both (&max_pos, &max_bpos);
24417 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24418 }
24419 }
24420 else if (row->truncated_on_right_p)
24421
24422
24423
24424 row->maxpos = it->current.pos;
24425 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24426
24427 row->maxpos = row->minpos;
24428 else
24429 emacs_abort ();
24430 }
24431 else
24432 row->maxpos = it->current.pos;
24433 }
24434
24435
24436
24437 static ptrdiff_t
24438 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24439 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24440 {
24441 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24442 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24443
24444 ptrdiff_t val;
24445 specpdl_ref pdl_count = SPECPDL_INDEX ();
24446 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24447 labeled_restrictions_remove_in_current_buffer ();
24448 Fwiden ();
24449 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24450 unbind_to (pdl_count, Qnil);
24451 return val;
24452 }
24453
24454
24455
24456 static ptrdiff_t
24457 display_count_lines_visually (struct it *it)
24458 {
24459 struct it tem_it;
24460 ptrdiff_t to;
24461 struct text_pos from;
24462
24463
24464
24465
24466
24467
24468 if (it->lnum_bytepos > 0)
24469 return it->lnum + 1;
24470 else
24471 {
24472 specpdl_ref count = SPECPDL_INDEX ();
24473
24474 if (IT_CHARPOS (*it) <= PT)
24475 {
24476 from = it->current.pos;
24477 to = PT;
24478 }
24479 else
24480 {
24481 SET_TEXT_POS (from, PT, PT_BYTE);
24482 to = IT_CHARPOS (*it);
24483 }
24484
24485
24486
24487 specbind (Qdisplay_line_numbers, Qrelative);
24488 start_display (&tem_it, it->w, from);
24489
24490
24491
24492
24493 move_it_to (&tem_it, to, -1,
24494 tem_it.last_visible_y
24495 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24496 -1, MOVE_TO_POS | MOVE_TO_Y);
24497 unbind_to (count, Qnil);
24498 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24499 }
24500 }
24501
24502
24503
24504
24505 static void
24506 maybe_produce_line_number (struct it *it)
24507 {
24508 ptrdiff_t last_line = it->lnum;
24509 ptrdiff_t start_from, bytepos;
24510 ptrdiff_t this_line;
24511 bool first_time = false;
24512 ptrdiff_t beg_byte;
24513 ptrdiff_t z_byte;
24514 bool line_numbers_wide;
24515 void *itdata = bidi_shelve_cache ();
24516
24517 if (display_line_numbers_offset
24518 && !display_line_numbers_widen
24519 && !EQ (Vdisplay_line_numbers, Qvisual)
24520 && !EQ (Vdisplay_line_numbers, Qrelative))
24521 line_numbers_wide = true;
24522 else
24523 line_numbers_wide = display_line_numbers_widen;
24524
24525 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24526 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24527
24528 if (EQ (Vdisplay_line_numbers, Qvisual))
24529 this_line = display_count_lines_visually (it);
24530 else
24531 {
24532 if (!last_line)
24533 {
24534
24535 if (it->w->base_line_number > 0
24536 && it->w->base_line_pos > 0
24537 && it->w->base_line_pos <= IT_CHARPOS (*it)
24538
24539
24540
24541
24542 && !(line_numbers_wide
24543 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24544 && !current_buffer->clip_changed)
24545 {
24546 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24547 last_line = it->w->base_line_number - 1;
24548 }
24549 else
24550 start_from = beg_byte;
24551 if (!it->lnum_bytepos)
24552 first_time = true;
24553 }
24554 else
24555 start_from = it->lnum_bytepos;
24556
24557
24558
24559
24560 if (!(beg_byte <= start_from && start_from <= z_byte))
24561 {
24562 last_line = 0;
24563 start_from = beg_byte;
24564 }
24565
24566 this_line =
24567 last_line + display_count_lines_logically (start_from,
24568 IT_BYTEPOS (*it),
24569 IT_CHARPOS (*it), &bytepos);
24570 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24571 eassert (bytepos == IT_BYTEPOS (*it));
24572 }
24573
24574
24575 if (this_line != last_line || !it->lnum_bytepos)
24576 {
24577 it->lnum = this_line;
24578 it->lnum_bytepos = IT_BYTEPOS (*it);
24579 }
24580
24581
24582 struct it tem_it;
24583 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24584 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24585 ptrdiff_t lnum_offset = -1;
24586 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24587 int current_lnum_face_id
24588 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24589
24590
24591 bool save_free_realized_faces = inhibit_free_realized_faces;
24592 inhibit_free_realized_faces = true;
24593
24594 if ((EQ (Vdisplay_line_numbers, Qrelative)
24595 || EQ (Vdisplay_line_numbers, Qvisual)
24596 || lnum_face_id != current_lnum_face_id)
24597 && !it->pt_lnum)
24598 {
24599 ptrdiff_t ignored;
24600 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24601 it->pt_lnum =
24602 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24603 PT, &ignored);
24604 else
24605 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24606 &ignored);
24607 }
24608
24609 if (!it->lnum_width)
24610 {
24611 if (FIXNATP (Vdisplay_line_numbers_width))
24612 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24613
24614
24615
24616 ptrdiff_t max_lnum;
24617
24618 if (NILP (Vdisplay_line_numbers_current_absolute)
24619 && (EQ (Vdisplay_line_numbers, Qrelative)
24620 || EQ (Vdisplay_line_numbers, Qvisual)))
24621
24622
24623 max_lnum = it->w->desired_matrix->nrows - 2;
24624 else if (EQ (Vdisplay_line_numbers, Qvisual))
24625 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24626 else
24627 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24628 max_lnum = max (1, max_lnum);
24629 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24630 eassert (it->lnum_width > 0);
24631 }
24632 if (EQ (Vdisplay_line_numbers, Qrelative))
24633 lnum_offset = it->pt_lnum;
24634 else if (EQ (Vdisplay_line_numbers, Qvisual))
24635 lnum_offset = 0;
24636 else if (display_line_numbers_offset)
24637 lnum_offset -= display_line_numbers_offset;
24638
24639
24640
24641 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24642 if ((EQ (Vdisplay_line_numbers, Qrelative)
24643 || EQ (Vdisplay_line_numbers, Qvisual))
24644 && lnum_to_display == 0
24645 && !NILP (Vdisplay_line_numbers_current_absolute))
24646 lnum_to_display = it->pt_lnum + 1;
24647
24648
24649
24650
24651
24652 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24653 strcat (lnum_buf, " ");
24654
24655
24656 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24657
24658 DEFAULT_FACE_ID);
24659 scratch_glyph_row.reversed_p = false;
24660 scratch_glyph_row.used[TEXT_AREA] = 0;
24661 SET_TEXT_POS (tem_it.position, 0, 0);
24662 tem_it.avoid_cursor_p = true;
24663 tem_it.bidi_p = true;
24664 tem_it.bidi_it.type = WEAK_EN;
24665
24666
24667
24668 tem_it.bidi_it.resolved_level = 2;
24669
24670
24671
24672 int width_limit =
24673 tem_it.last_visible_x - tem_it.first_visible_x
24674 - 3 * FRAME_COLUMN_WIDTH (it->f);
24675
24676 tem_it.face_id = lnum_face_id;
24677
24678
24679 if (lnum_face_id != current_lnum_face_id
24680 && (EQ (Vdisplay_line_numbers, Qvisual)
24681 ? this_line == 0
24682 : this_line == it->pt_lnum)
24683 && it->what != IT_EOB)
24684 tem_it.face_id = current_lnum_face_id;
24685 else if (!beyond_zv)
24686 {
24687 if (display_line_numbers_major_tick > 0
24688 && (lnum_to_display % display_line_numbers_major_tick == 0))
24689 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24690 0, DEFAULT_FACE_ID);
24691 else if (display_line_numbers_minor_tick > 0
24692 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24693 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24694 0, DEFAULT_FACE_ID);
24695 }
24696
24697
24698 for (const char *p = lnum_buf; *p; p++)
24699 {
24700
24701
24702 if (beyond_zv
24703
24704 || (!EQ (Vdisplay_line_numbers, Qvisual)
24705 && (it->continuation_lines_width > 0
24706 || (this_line == last_line && !first_time))))
24707 tem_it.c = tem_it.char_to_display = ' ';
24708 else
24709 tem_it.c = tem_it.char_to_display = *p;
24710 tem_it.len = 1;
24711
24712 SET_TEXT_POS (tem_it.position, -1, -1);
24713 PRODUCE_GLYPHS (&tem_it);
24714
24715
24716
24717 if (tem_it.current_x >= width_limit)
24718 {
24719 it->lnum_width = 0;
24720 it->lnum_pixel_width = 0;
24721 bidi_unshelve_cache (itdata, false);
24722 inhibit_free_realized_faces = save_free_realized_faces;
24723 return;
24724 }
24725 }
24726
24727 inhibit_free_realized_faces = save_free_realized_faces;
24728
24729
24730 it->lnum_pixel_width = tem_it.current_x;
24731
24732 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24733 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24734 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24735 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24736
24737 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24738
24739 for ( ; g < e; g++)
24740 {
24741 it->current_x += g->pixel_width;
24742
24743
24744
24745 if (it->current_x > it->first_visible_x)
24746 it->hpos++;
24747 if (p)
24748 {
24749 *p++ = *g;
24750 (*u)++;
24751 }
24752 }
24753
24754
24755
24756
24757 if (!beyond_zv)
24758 {
24759 if (it->glyph_row)
24760 {
24761 struct glyph_row *row = it->glyph_row;
24762
24763 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24764 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24765 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24766 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24767 tem_it.max_phys_descent);
24768 }
24769 else
24770 {
24771 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24772 it->max_descent = max (it->max_descent, tem_it.max_descent);
24773 it->max_phys_ascent = max (it->max_phys_ascent,
24774 tem_it.max_phys_ascent);
24775 it->max_phys_descent = max (it->max_phys_descent,
24776 tem_it.max_phys_descent);
24777 }
24778 }
24779
24780 it->line_number_produced_p = true;
24781
24782 bidi_unshelve_cache (itdata, false);
24783 }
24784
24785
24786
24787 static bool
24788 should_produce_line_number (struct it *it)
24789 {
24790 if (NILP (Vdisplay_line_numbers))
24791 return false;
24792
24793
24794 if (MINI_WINDOW_P (it->w))
24795 return false;
24796
24797 #ifdef HAVE_WINDOW_SYSTEM
24798
24799 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24800 return false;
24801 #endif
24802
24803
24804
24805
24806
24807 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24808 Qdisplay_line_numbers_disable,
24809 it->window);
24810
24811
24812
24813 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24814 val = disable_line_numbers_overlay_at_eob ();
24815 return NILP (val) ? true : false;
24816 }
24817
24818
24819
24820
24821
24822 static bool
24823 row_text_area_empty (struct glyph_row *row)
24824 {
24825 if (!row->reversed_p)
24826 {
24827 for (struct glyph *g = row->glyphs[TEXT_AREA];
24828 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24829 g++)
24830 if (!NILP (g->object) || g->charpos > 0)
24831 return false;
24832 }
24833 else
24834 {
24835 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24836 g > row->glyphs[TEXT_AREA];
24837 g--)
24838 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24839 return false;
24840 }
24841
24842 return true;
24843 }
24844
24845
24846
24847
24848
24849
24850
24851
24852 static bool
24853 display_line (struct it *it, int cursor_vpos)
24854 {
24855 struct glyph_row *row = it->glyph_row;
24856 Lisp_Object overlay_arrow_string;
24857 struct it wrap_it;
24858 void *wrap_data = NULL;
24859 bool may_wrap = false;
24860 int wrap_x UNINIT;
24861 int wrap_row_used = -1;
24862 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24863 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24864 int wrap_row_extra_line_spacing UNINIT;
24865 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24866 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24867 int cvpos;
24868 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24869 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24870 bool pending_handle_line_prefix = false;
24871 int tab_line = window_wants_tab_line (it->w);
24872 int header_line = window_wants_header_line (it->w);
24873 bool hscroll_this_line = (cursor_vpos >= 0
24874 && it->vpos == cursor_vpos - tab_line - header_line
24875 && hscrolling_current_line_p (it->w));
24876 int first_visible_x = it->first_visible_x;
24877 int last_visible_x = it->last_visible_x;
24878 int x_incr = 0;
24879
24880
24881 eassert (it->hpos == 0 && it->current_x == 0);
24882
24883 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24884 >= it->w->desired_matrix->nrows)
24885 {
24886 it->w->nrows_scale_factor++;
24887 it->f->fonts_changed = true;
24888 return false;
24889 }
24890
24891
24892 prepare_desired_row (it->w, row, false);
24893
24894 row->y = it->current_y;
24895 row->start = it->start;
24896 row->continuation_lines_width = it->continuation_lines_width;
24897 row->displays_text_p = true;
24898 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24899 it->starts_in_middle_of_char_p = false;
24900 it->stretch_adjust = 0;
24901 it->line_number_produced_p = false;
24902
24903
24904
24905
24906 if (hscroll_this_line)
24907 x_incr =
24908 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24909 * FRAME_COLUMN_WIDTH (it->f);
24910
24911 bool line_number_needed = should_produce_line_number (it);
24912
24913
24914
24915
24916 if (it->current_x < it->first_visible_x + x_incr)
24917 {
24918 enum move_it_result move_result;
24919
24920 this_line_min_pos = row->start.pos;
24921 if (hscroll_this_line)
24922 {
24923 it->first_visible_x += x_incr;
24924 it->last_visible_x += x_incr;
24925 }
24926 if (current_buffer->long_line_optimizations_p
24927 && it->line_wrap == TRUNCATE
24928 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24929 {
24930
24931
24932
24933
24934 ptrdiff_t chars_to_skip =
24935 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24936 move_result = fast_move_it_horizontally (it, chars_to_skip);
24937
24938 if (move_result == MOVE_X_REACHED)
24939 it->current_x = it->first_visible_x;
24940 else
24941 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24942 }
24943 else
24944 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24945 MOVE_TO_POS | MOVE_TO_X);
24946
24947
24948
24949
24950
24951
24952 if (it->current_x < it->first_visible_x
24953 && (move_result == MOVE_NEWLINE_OR_CR
24954 || move_result == MOVE_POS_MATCH_OR_ZV))
24955 it->current_x = it->first_visible_x;
24956
24957
24958
24959 it->line_number_produced_p = false;
24960
24961
24962
24963
24964
24965
24966
24967
24968 min_pos = CHARPOS (this_line_min_pos);
24969 min_bpos = BYTEPOS (this_line_min_pos);
24970
24971
24972 if (line_number_needed)
24973 maybe_produce_line_number (it);
24974 }
24975 else if (it->area == TEXT_AREA)
24976 {
24977
24978 if (line_number_needed)
24979 maybe_produce_line_number (it);
24980
24981
24982
24983 handle_line_prefix (it);
24984 }
24985 else
24986 {
24987
24988
24989
24990
24991
24992
24993
24994 pending_handle_line_prefix = true;
24995 }
24996
24997
24998
24999 row->ascent = it->max_ascent;
25000 row->height = it->max_ascent + it->max_descent;
25001 row->phys_ascent = it->max_phys_ascent;
25002 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
25003 row->extra_line_spacing = it->max_extra_line_spacing;
25004
25005
25006 #define RECORD_MAX_MIN_POS(IT) \
25007 do \
25008 { \
25009 bool composition_p \
25010 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
25011 ptrdiff_t current_pos = \
25012 composition_p ? (IT)->cmp_it.charpos \
25013 : IT_CHARPOS (*(IT)); \
25014 ptrdiff_t current_bpos = \
25015 composition_p ? CHAR_TO_BYTE (current_pos) \
25016 : IT_BYTEPOS (*(IT)); \
25017 if (current_pos < min_pos) \
25018 { \
25019 min_pos = current_pos; \
25020 min_bpos = current_bpos; \
25021 } \
25022 if (IT_CHARPOS (*it) > max_pos) \
25023 { \
25024 max_pos = IT_CHARPOS (*it); \
25025 max_bpos = IT_BYTEPOS (*it); \
25026 } \
25027 } \
25028 while (false)
25029
25030
25031
25032 while (true)
25033 {
25034 int n_glyphs_before, hpos_before, x_before;
25035 int x, nglyphs;
25036 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
25037
25038
25039
25040 if (!get_next_display_element (it))
25041 {
25042 bool row_has_glyphs = false;
25043
25044
25045
25046
25047 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25048 row->exact_window_width_line_p = true;
25049 else if ((append_space_for_newline (it, true)
25050 && row->used[TEXT_AREA] == 1)
25051 || row->used[TEXT_AREA] == 0
25052 || (row_has_glyphs = row_text_area_empty (row)))
25053 {
25054 row->glyphs[TEXT_AREA]->charpos = -1;
25055
25056
25057 if (!row_has_glyphs)
25058 row->displays_text_p = false;
25059
25060 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
25061 && (!MINI_WINDOW_P (it->w)))
25062 row->indicate_empty_line_p = true;
25063 }
25064
25065 it->continuation_lines_width = 0;
25066
25067
25068
25069
25070 it->font_height = Qnil;
25071 it->voffset = 0;
25072 row->ends_at_zv_p = true;
25073
25074
25075
25076
25077
25078
25079
25080
25081 if (row->reversed_p
25082 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
25083 != DEFAULT_FACE_ID)
25084 extend_face_to_end_of_line (it);
25085 break;
25086 }
25087
25088
25089
25090 n_glyphs_before = row->used[TEXT_AREA];
25091 x = it->current_x;
25092
25093
25094
25095 if (it->line_wrap != TRUNCATE)
25096 {
25097 ascent = it->max_ascent;
25098 descent = it->max_descent;
25099 phys_ascent = it->max_phys_ascent;
25100 phys_descent = it->max_phys_descent;
25101
25102 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
25103 {
25104 bool next_may_wrap = may_wrap;
25105
25106 if (char_can_wrap_after (it))
25107 next_may_wrap = true;
25108 else
25109 next_may_wrap = false;
25110
25111 if (may_wrap && char_can_wrap_before (it))
25112 {
25113 SAVE_IT (wrap_it, *it, wrap_data);
25114 wrap_x = x;
25115 wrap_row_used = row->used[TEXT_AREA];
25116 wrap_row_ascent = row->ascent;
25117 wrap_row_height = row->height;
25118 wrap_row_phys_ascent = row->phys_ascent;
25119 wrap_row_phys_height = row->phys_height;
25120 wrap_row_extra_line_spacing = row->extra_line_spacing;
25121 wrap_row_min_pos = min_pos;
25122 wrap_row_min_bpos = min_bpos;
25123 wrap_row_max_pos = max_pos;
25124 wrap_row_max_bpos = max_bpos;
25125 }
25126
25127 may_wrap = next_may_wrap;
25128 }
25129 }
25130
25131 PRODUCE_GLYPHS (it);
25132
25133
25134
25135 if (it->area != TEXT_AREA)
25136 {
25137 row->ascent = max (row->ascent, it->max_ascent);
25138 row->height = max (row->height, it->max_ascent + it->max_descent);
25139 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25140 row->phys_height = max (row->phys_height,
25141 it->max_phys_ascent + it->max_phys_descent);
25142 row->extra_line_spacing = max (row->extra_line_spacing,
25143 it->max_extra_line_spacing);
25144 set_iterator_to_next (it, true);
25145
25146
25147
25148 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25149 {
25150
25151 if (line_number_needed)
25152 maybe_produce_line_number (it);
25153
25154 pending_handle_line_prefix = false;
25155 handle_line_prefix (it);
25156 }
25157 continue;
25158 }
25159
25160
25161
25162
25163
25164
25165
25166
25167
25168
25169 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
25170 hpos_before = it->hpos;
25171 x_before = x;
25172
25173 if (
25174 nglyphs > 0
25175
25176 && it->current_x < it->last_visible_x)
25177 {
25178 it->hpos += nglyphs;
25179 row->ascent = max (row->ascent, it->max_ascent);
25180 row->height = max (row->height, it->max_ascent + it->max_descent);
25181 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25182 row->phys_height = max (row->phys_height,
25183 it->max_phys_ascent + it->max_phys_descent);
25184 row->extra_line_spacing = max (row->extra_line_spacing,
25185 it->max_extra_line_spacing);
25186 if (it->current_x - it->pixel_width < it->first_visible_x
25187
25188
25189
25190 && !line_number_needed
25191
25192
25193
25194
25195 && !row->reversed_p)
25196 row->x = x - it->first_visible_x;
25197
25198
25199 if (it->bidi_p)
25200 RECORD_MAX_MIN_POS (it);
25201 }
25202 else
25203 {
25204 int i, new_x;
25205 struct glyph *glyph;
25206
25207 for (i = 0; i < nglyphs; ++i, x = new_x)
25208 {
25209
25210
25211
25212 if (!row->reversed_p)
25213 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25214 else
25215 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25216 new_x = x + glyph->pixel_width;
25217
25218 if (
25219 it->line_wrap != TRUNCATE
25220 && (
25221 new_x > it->last_visible_x
25222
25223 || (new_x == it->last_visible_x
25224 && FRAME_WINDOW_P (it->f)
25225 && (row->reversed_p
25226 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25227 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25228 {
25229
25230
25231 if (it->hpos == 0
25232 || (new_x == it->last_visible_x
25233 && FRAME_WINDOW_P (it->f)
25234 && (row->reversed_p
25235 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25236 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25237 {
25238
25239
25240
25241
25242 row->continued_p = true;
25243 it->current_x = new_x;
25244 it->continuation_lines_width += new_x;
25245 ++it->hpos;
25246 if (i == nglyphs - 1)
25247 {
25248
25249
25250 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25251 && wrap_row_used > 0
25252
25253
25254
25255
25256
25257
25258
25259
25260
25261
25262 && (!may_wrap || !char_can_wrap_before (it)))
25263 goto back_to_wrap;
25264
25265
25266
25267
25268 if (it->bidi_p)
25269 RECORD_MAX_MIN_POS (it);
25270 set_iterator_to_next (it, true);
25271 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25272 {
25273 if (!get_next_display_element (it))
25274 {
25275 row->exact_window_width_line_p = true;
25276 it->continuation_lines_width = 0;
25277 it->font_height = Qnil;
25278 it->voffset = 0;
25279 row->continued_p = false;
25280 row->ends_at_zv_p = true;
25281 }
25282 else if (ITERATOR_AT_END_OF_LINE_P (it))
25283 {
25284 row->continued_p = false;
25285 row->exact_window_width_line_p = true;
25286 }
25287
25288
25289 else if (wrap_row_used > 0
25290
25291
25292
25293
25294
25295
25296
25297
25298
25299 && (!may_wrap || !char_can_wrap_before (it)))
25300 goto back_to_wrap;
25301
25302 }
25303 }
25304 else if (it->bidi_p)
25305 RECORD_MAX_MIN_POS (it);
25306 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25307 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25308 extend_face_to_end_of_line (it);
25309 }
25310 else if (CHAR_GLYPH_PADDING_P (*glyph)
25311 && !FRAME_WINDOW_P (it->f))
25312 {
25313
25314
25315
25316 if (row->reversed_p)
25317 unproduce_glyphs (it, row->used[TEXT_AREA]
25318 - n_glyphs_before);
25319 row->used[TEXT_AREA] = n_glyphs_before;
25320
25321
25322
25323 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25324 < row->glyphs[1 + TEXT_AREA])
25325 produce_special_glyphs (it, IT_CONTINUATION);
25326
25327 row->continued_p = true;
25328 it->current_x = x_before;
25329 it->continuation_lines_width += x_before;
25330
25331
25332
25333 it->max_ascent = ascent;
25334 it->max_descent = descent;
25335 it->max_phys_ascent = phys_ascent;
25336 it->max_phys_descent = phys_descent;
25337 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25338 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25339 extend_face_to_end_of_line (it);
25340 }
25341 else if (wrap_row_used > 0)
25342 {
25343 back_to_wrap:
25344 if (row->reversed_p)
25345 unproduce_glyphs (it,
25346 row->used[TEXT_AREA] - wrap_row_used);
25347 RESTORE_IT (it, &wrap_it, wrap_data);
25348 it->continuation_lines_width += wrap_x;
25349 row->used[TEXT_AREA] = wrap_row_used;
25350 row->ascent = wrap_row_ascent;
25351 row->height = wrap_row_height;
25352 row->phys_ascent = wrap_row_phys_ascent;
25353 row->phys_height = wrap_row_phys_height;
25354 row->extra_line_spacing = wrap_row_extra_line_spacing;
25355 min_pos = wrap_row_min_pos;
25356 min_bpos = wrap_row_min_bpos;
25357 max_pos = wrap_row_max_pos;
25358 max_bpos = wrap_row_max_bpos;
25359 row->continued_p = true;
25360 row->ends_at_zv_p = false;
25361 row->exact_window_width_line_p = false;
25362
25363
25364
25365 extend_face_to_end_of_line (it);
25366 }
25367 else if ((it->what == IT_CHARACTER
25368 || it->what == IT_STRETCH
25369 || it->what == IT_COMPOSITION)
25370 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25371 {
25372
25373
25374
25375
25376
25377 if ((row->reversed_p
25378 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25379 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25380 produce_special_glyphs (it, IT_CONTINUATION);
25381 it->continuation_lines_width += it->last_visible_x;
25382 row->ends_in_middle_of_char_p = true;
25383 row->continued_p = true;
25384 glyph->pixel_width = it->last_visible_x - x;
25385 it->starts_in_middle_of_char_p = true;
25386 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25387 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25388 extend_face_to_end_of_line (it);
25389 }
25390 else
25391 {
25392
25393
25394
25395 if (row->reversed_p)
25396 unproduce_glyphs (it, row->used[TEXT_AREA]
25397 - (n_glyphs_before + i));
25398 row->used[TEXT_AREA] = n_glyphs_before + i;
25399
25400
25401 it->current_x = x_before;
25402 it->continuation_lines_width += x;
25403 if (!FRAME_WINDOW_P (it->f)
25404 || (row->reversed_p
25405 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25406 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25407 produce_special_glyphs (it, IT_CONTINUATION);
25408 row->continued_p = true;
25409
25410 extend_face_to_end_of_line (it);
25411
25412 if (nglyphs > 1 && i > 0)
25413 {
25414 row->ends_in_middle_of_char_p = true;
25415 it->starts_in_middle_of_char_p = true;
25416 }
25417
25418
25419
25420 it->max_ascent = ascent;
25421 it->max_descent = descent;
25422 it->max_phys_ascent = phys_ascent;
25423 it->max_phys_descent = phys_descent;
25424 }
25425
25426 break;
25427 }
25428 else if (new_x > it->first_visible_x)
25429 {
25430
25431 ++it->hpos;
25432
25433
25434
25435
25436 if (it->bidi_p)
25437 RECORD_MAX_MIN_POS (it);
25438
25439 if (x < it->first_visible_x && !row->reversed_p
25440 && !line_number_needed)
25441
25442
25443
25444
25445
25446
25447 row->x = x - it->first_visible_x;
25448
25449
25450
25451
25452
25453
25454 if (row->reversed_p
25455 && new_x > it->last_visible_x
25456 && !line_number_needed
25457 && !(it->line_wrap == TRUNCATE
25458 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25459 {
25460 eassert (FRAME_WINDOW_P (it->f));
25461 row->x = it->last_visible_x - new_x;
25462 }
25463 }
25464 else
25465 {
25466
25467
25468
25469
25470
25471 eassert (it->first_visible_x <= it->last_visible_x);
25472 }
25473 }
25474
25475
25476 if (it->bidi_p && nglyphs == 0)
25477 RECORD_MAX_MIN_POS (it);
25478
25479 row->ascent = max (row->ascent, it->max_ascent);
25480 row->height = max (row->height, it->max_ascent + it->max_descent);
25481 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25482 row->phys_height = max (row->phys_height,
25483 it->max_phys_ascent + it->max_phys_descent);
25484 row->extra_line_spacing = max (row->extra_line_spacing,
25485 it->max_extra_line_spacing);
25486
25487
25488 if (row->continued_p || row->ends_at_zv_p)
25489 break;
25490 }
25491
25492 at_end_of_line:
25493
25494
25495
25496 if (ITERATOR_AT_END_OF_LINE_P (it))
25497 {
25498 int used_before = row->used[TEXT_AREA];
25499
25500 row->ends_in_newline_from_string_p = STRINGP (it->object);
25501
25502
25503
25504 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25505 append_space_for_newline (it, false);
25506
25507
25508 extend_face_to_end_of_line (it);
25509
25510
25511 if (used_before == 0)
25512 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25513
25514
25515
25516 it->eol_pos = it->current.pos;
25517
25518
25519 set_iterator_to_next (it, true);
25520 it->continuation_lines_width = 0;
25521 break;
25522 }
25523
25524
25525
25526
25527
25528
25529
25530
25531 bool overwide_wrap_prefix =
25532 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25533 && it->sp > 0 && it->method == GET_FROM_STRETCH
25534 && it->current_x >= it->last_visible_x
25535 && it->continuation_lines_width > 0
25536 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25537
25538
25539
25540 if (!overwide_wrap_prefix)
25541 set_iterator_to_next (it, true);
25542
25543
25544
25545 if (it->line_wrap == TRUNCATE
25546 && ((FRAME_WINDOW_P (it->f)
25547
25548
25549
25550
25551 && ((row->reversed_p
25552 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25553 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25554 || it->what == IT_IMAGE))
25555 ? (it->current_x >= it->last_visible_x)
25556 : (it->current_x > it->last_visible_x)))
25557 {
25558
25559 if (!FRAME_WINDOW_P (it->f)
25560 || (row->reversed_p
25561 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25562 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25563 {
25564 int i, n;
25565
25566 if (!row->reversed_p)
25567 {
25568 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25569 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25570 break;
25571 }
25572 else
25573 {
25574 for (i = 0; i < row->used[TEXT_AREA]; i++)
25575 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25576 break;
25577
25578
25579
25580
25581
25582 unproduce_glyphs (it, i + 1);
25583
25584 i = row->used[TEXT_AREA] - (i + 1);
25585 }
25586
25587
25588
25589
25590 if (it->current_x > it->last_visible_x)
25591 {
25592 it->current_x = x_before;
25593 if (!FRAME_WINDOW_P (it->f))
25594 {
25595 for (n = row->used[TEXT_AREA]; i < n; ++i)
25596 {
25597 row->used[TEXT_AREA] = i;
25598 produce_special_glyphs (it, IT_TRUNCATION);
25599 }
25600 }
25601 else
25602 {
25603 row->used[TEXT_AREA] = i;
25604 produce_special_glyphs (it, IT_TRUNCATION);
25605 }
25606 it->hpos = hpos_before;
25607 }
25608 }
25609 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25610 {
25611
25612 if (!get_next_display_element (it))
25613 {
25614 it->continuation_lines_width = 0;
25615 it->font_height = Qnil;
25616 it->voffset = 0;
25617 row->ends_at_zv_p = true;
25618 row->exact_window_width_line_p = true;
25619 break;
25620 }
25621 if (ITERATOR_AT_END_OF_LINE_P (it))
25622 {
25623 row->exact_window_width_line_p = true;
25624 goto at_end_of_line;
25625 }
25626 it->current_x = x_before;
25627 it->hpos = hpos_before;
25628 }
25629
25630 row->truncated_on_right_p = true;
25631 it->continuation_lines_width = 0;
25632 reseat_at_next_visible_line_start (it, false);
25633
25634
25635
25636
25637 if (IT_BYTEPOS (*it) > BEG_BYTE)
25638 row->ends_at_zv_p =
25639 IT_BYTEPOS (*it) >= ZV_BYTE
25640 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25641 else
25642 row->ends_at_zv_p = false;
25643 break;
25644 }
25645 }
25646
25647 if (wrap_data)
25648 bidi_unshelve_cache (wrap_data, true);
25649
25650
25651
25652 if (it->first_visible_x
25653 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25654 {
25655 if (!FRAME_WINDOW_P (it->f)
25656 || (((row->reversed_p
25657 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25658 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25659
25660
25661 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25662 insert_left_trunc_glyphs (it);
25663 row->truncated_on_left_p = true;
25664 }
25665
25666
25667
25668
25669
25670
25671 row->end = it->current;
25672 if (!it->bidi_p)
25673 {
25674 row->minpos = row->start.pos;
25675 row->maxpos = row->end.pos;
25676 }
25677 else
25678 {
25679
25680
25681
25682
25683 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25684 }
25685
25686
25687
25688
25689
25690 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25691 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25692 !NILP (overlay_arrow_string)))
25693 {
25694
25695 if (STRINGP (overlay_arrow_string))
25696 {
25697 struct glyph_row *arrow_row
25698 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25699 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25700 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25701 struct glyph *p = row->glyphs[TEXT_AREA];
25702 struct glyph *p2, *end;
25703
25704
25705 while (glyph < arrow_end)
25706 *p++ = *glyph++;
25707
25708
25709 p2 = p;
25710 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25711 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25712 ++p2;
25713 if (p2 > p)
25714 {
25715 while (p2 < end)
25716 *p++ = *p2++;
25717 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25718 }
25719 }
25720 else
25721 {
25722 eassert (FIXNUMP (overlay_arrow_string));
25723 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25724 }
25725 overlay_arrow_seen = true;
25726 }
25727
25728
25729 if (!NILP (Vshow_trailing_whitespace))
25730 highlight_trailing_whitespace (it);
25731
25732
25733 compute_line_metrics (it);
25734
25735
25736
25737
25738
25739
25740
25741 row->ends_in_ellipsis_p
25742 = (it->method == GET_FROM_DISPLAY_VECTOR
25743 && it->ellipsis_p);
25744
25745
25746 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25747 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25748 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25749 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25750
25751 it->left_user_fringe_bitmap = 0;
25752 it->left_user_fringe_face_id = 0;
25753 it->right_user_fringe_bitmap = 0;
25754 it->right_user_fringe_face_id = 0;
25755
25756
25757
25758
25759
25760
25761 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25762 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25763 row->redraw_fringe_bitmaps_p = true;
25764
25765
25766 cvpos = it->w->cursor.vpos;
25767 if ((cvpos < 0
25768
25769
25770
25771
25772
25773
25774
25775
25776 || (it->bidi_p
25777 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25778 && PT >= MATRIX_ROW_START_CHARPOS (row)
25779 && PT <= MATRIX_ROW_END_CHARPOS (row)
25780 && cursor_row_p (row))
25781 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25782
25783
25784
25785
25786
25787 it->current_x = it->hpos = 0;
25788 it->current_y += row->height;
25789
25790
25791 if (hscroll_this_line)
25792 {
25793 it->first_visible_x = first_visible_x;
25794 it->last_visible_x = last_visible_x;
25795 }
25796 SET_TEXT_POS (it->eol_pos, 0, 0);
25797 ++it->vpos;
25798 ++it->glyph_row;
25799
25800
25801
25802
25803 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25804 it->glyph_row->reversed_p = row->reversed_p;
25805 it->start = row->end;
25806 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25807
25808 #undef RECORD_MAX_MIN_POS
25809 }
25810
25811 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25812 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25813 doc:
25814
25815
25816
25817
25818
25819
25820
25821
25822 )
25823 (Lisp_Object buffer)
25824 {
25825 struct buffer *buf = current_buffer;
25826 struct buffer *old = buf;
25827
25828 if (! NILP (buffer))
25829 {
25830 CHECK_BUFFER (buffer);
25831 buf = XBUFFER (buffer);
25832 }
25833
25834 if (NILP (BVAR (buf, bidi_display_reordering))
25835 || NILP (BVAR (buf, enable_multibyte_characters))
25836
25837
25838 || redisplay__inhibit_bidi)
25839 return Qleft_to_right;
25840 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25841 return BVAR (buf, bidi_paragraph_direction);
25842 else
25843 {
25844
25845
25846
25847 struct bidi_it itb;
25848 ptrdiff_t pos = BUF_PT (buf);
25849 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25850 int c;
25851 void *itb_data = bidi_shelve_cache ();
25852
25853 set_buffer_temp (buf);
25854
25855
25856
25857
25858
25859 if (pos >= ZV && pos > BEGV)
25860 dec_both (&pos, &bytepos);
25861 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25862 if (fast_looking_at (trailing_white_space,
25863 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25864 {
25865 while ((c = FETCH_BYTE (bytepos)) == '\n'
25866 || c == ' ' || c == '\t' || c == '\f')
25867 {
25868 if (bytepos <= BEGV_BYTE)
25869 break;
25870 bytepos--;
25871 pos--;
25872 }
25873 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25874 bytepos--;
25875 }
25876 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25877 itb.paragraph_dir = NEUTRAL_DIR;
25878 itb.string.s = NULL;
25879 itb.string.lstring = Qnil;
25880 itb.string.bufpos = 0;
25881 itb.string.from_disp_str = false;
25882 itb.string.unibyte = false;
25883
25884
25885
25886 itb.w = NULL;
25887 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25888 bidi_unshelve_cache (itb_data, false);
25889 set_buffer_temp (old);
25890 switch (itb.paragraph_dir)
25891 {
25892 case L2R:
25893 return Qleft_to_right;
25894 break;
25895 case R2L:
25896 return Qright_to_left;
25897 break;
25898 default:
25899 emacs_abort ();
25900 }
25901 }
25902 }
25903
25904 DEFUN ("bidi-find-overridden-directionality",
25905 Fbidi_find_overridden_directionality,
25906 Sbidi_find_overridden_directionality, 3, 4, 0,
25907 doc:
25908
25909
25910
25911
25912
25913
25914
25915
25916
25917
25918
25919
25920
25921
25922
25923
25924
25925
25926
25927
25928
25929
25930
25931
25932
25933
25934
25935
25936
25937
25938
25939
25940
25941
25942
25943
25944 )
25945 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25946 {
25947 struct buffer *buf = current_buffer;
25948 struct buffer *old = buf;
25949 struct window *w = NULL;
25950 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25951 struct bidi_it itb;
25952 ptrdiff_t from_pos, to_pos, from_bpos;
25953 void *itb_data;
25954
25955 if (!NILP (object))
25956 {
25957 if (BUFFERP (object))
25958 buf = XBUFFER (object);
25959 else if (WINDOWP (object))
25960 {
25961 w = decode_live_window (object);
25962 buf = XBUFFER (w->contents);
25963 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25964 }
25965 else
25966 CHECK_STRING (object);
25967 }
25968
25969 if (STRINGP (object))
25970 {
25971
25972
25973 if (!STRING_MULTIBYTE (object)
25974
25975
25976
25977 || redisplay__inhibit_bidi)
25978 return Qnil;
25979
25980 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
25981 if (from_pos >= SCHARS (object))
25982 return Qnil;
25983
25984
25985 itb_data = bidi_shelve_cache ();
25986 itb.paragraph_dir = NEUTRAL_DIR;
25987 itb.string.lstring = object;
25988 itb.string.s = NULL;
25989 itb.string.schars = SCHARS (object);
25990 itb.string.bufpos = 0;
25991 itb.string.from_disp_str = false;
25992 itb.string.unibyte = false;
25993 itb.w = w;
25994 bidi_init_it (0, 0, frame_window_p, &itb);
25995 }
25996 else
25997 {
25998
25999
26000 if (NILP (BVAR (buf, bidi_display_reordering))
26001 || NILP (BVAR (buf, enable_multibyte_characters))
26002
26003
26004
26005 || redisplay__inhibit_bidi)
26006 return Qnil;
26007
26008 set_buffer_temp (buf);
26009 validate_region (&from, &to);
26010 from_pos = XFIXNUM (from);
26011 to_pos = XFIXNUM (to);
26012 if (from_pos >= ZV)
26013 return Qnil;
26014
26015
26016 itb_data = bidi_shelve_cache ();
26017 from_bpos = CHAR_TO_BYTE (from_pos);
26018 if (from_pos == BEGV)
26019 {
26020 itb.charpos = BEGV;
26021 itb.bytepos = BEGV_BYTE;
26022 }
26023 else if (FETCH_BYTE (from_bpos - 1) == '\n')
26024 {
26025 itb.charpos = from_pos;
26026 itb.bytepos = from_bpos;
26027 }
26028 else
26029 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
26030 -1, &itb.bytepos);
26031 itb.paragraph_dir = NEUTRAL_DIR;
26032 itb.string.s = NULL;
26033 itb.string.lstring = Qnil;
26034 itb.string.bufpos = 0;
26035 itb.string.from_disp_str = false;
26036 itb.string.unibyte = false;
26037 itb.w = w;
26038 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
26039 }
26040
26041 ptrdiff_t found;
26042 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
26043 do {
26044 bidi_paragraph_init (bdir, &itb, false);
26045 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
26046 ;
26047 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
26048
26049 bidi_unshelve_cache (itb_data, false);
26050 set_buffer_temp (old);
26051
26052 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
26053 }
26054
26055 DEFUN ("move-point-visually", Fmove_point_visually,
26056 Smove_point_visually, 1, 1, 0,
26057 doc:
26058
26059
26060
26061 )
26062 (Lisp_Object direction)
26063 {
26064 struct window *w = XWINDOW (selected_window);
26065 struct buffer *b = XBUFFER (w->contents);
26066 struct glyph_row *row;
26067 int dir;
26068 Lisp_Object paragraph_dir;
26069
26070 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
26071 (!(ROW)->continued_p \
26072 && NILP ((GLYPH)->object) \
26073 && (GLYPH)->type == CHAR_GLYPH \
26074 && (GLYPH)->u.ch == ' ' \
26075 && (GLYPH)->charpos >= 0 \
26076 && !(GLYPH)->avoid_cursor_p)
26077
26078 CHECK_FIXNUM (direction);
26079 dir = XFIXNUM (direction);
26080 if (dir > 0)
26081 dir = 1;
26082 else
26083 dir = -1;
26084
26085
26086
26087
26088 if (w->window_end_valid
26089 && !windows_or_buffers_changed
26090 && b
26091 && !b->clip_changed
26092 && !b->prevent_redisplay_optimizations_p
26093 && !window_outdated (w)
26094
26095
26096
26097 && w->last_point == BUF_PT (b)
26098 && w->cursor.vpos >= 0
26099 && w->cursor.vpos < w->current_matrix->nrows
26100 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
26101 {
26102 struct glyph *g = row->glyphs[TEXT_AREA];
26103 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
26104 struct glyph *gpt = g + w->cursor.hpos;
26105
26106 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
26107 {
26108 if (BUFFERP (g->object) && g->charpos != PT)
26109 {
26110 SET_PT (g->charpos);
26111 w->cursor.vpos = -1;
26112 return make_fixnum (PT);
26113 }
26114 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
26115 {
26116 ptrdiff_t new_pos;
26117
26118 if (BUFFERP (gpt->object))
26119 {
26120 new_pos = PT;
26121 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
26122 new_pos += (row->reversed_p ? -dir : dir);
26123 else
26124 new_pos -= (row->reversed_p ? -dir : dir);
26125 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
26126
26127
26128 if (new_pos == PT)
26129 break;
26130 }
26131 else if (BUFFERP (g->object))
26132 new_pos = g->charpos;
26133 else
26134 break;
26135 SET_PT (new_pos);
26136 w->cursor.vpos = -1;
26137 return make_fixnum (PT);
26138 }
26139 else if (ROW_GLYPH_NEWLINE_P (row, g))
26140 {
26141
26142
26143
26144 if (g->charpos > 0)
26145 SET_PT (g->charpos);
26146 else if (row->ends_at_zv_p && PT != ZV)
26147 SET_PT (ZV);
26148 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
26149 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26150 else
26151 break;
26152 w->cursor.vpos = -1;
26153 return make_fixnum (PT);
26154 }
26155 }
26156 if (g == e || NILP (g->object))
26157 {
26158 if (row->truncated_on_left_p || row->truncated_on_right_p)
26159 goto simulate_display;
26160 if (!row->reversed_p)
26161 row += dir;
26162 else
26163 row -= dir;
26164 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
26165 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
26166 goto simulate_display;
26167
26168 if (dir > 0)
26169 {
26170 if (row->reversed_p && !row->continued_p)
26171 {
26172 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26173 w->cursor.vpos = -1;
26174 return make_fixnum (PT);
26175 }
26176 g = row->glyphs[TEXT_AREA];
26177 e = g + row->used[TEXT_AREA];
26178 for ( ; g < e; g++)
26179 {
26180 if (BUFFERP (g->object)
26181
26182
26183
26184 || ROW_GLYPH_NEWLINE_P (row, g)
26185
26186
26187 || (row->ends_at_zv_p
26188 && !row->reversed_p
26189 && NILP (g->object)
26190 && g->type == CHAR_GLYPH
26191 && g->u.ch == ' '))
26192 {
26193 if (g->charpos > 0)
26194 SET_PT (g->charpos);
26195 else if (!row->reversed_p
26196 && row->ends_at_zv_p
26197 && PT != ZV)
26198 SET_PT (ZV);
26199 else
26200 continue;
26201 w->cursor.vpos = -1;
26202 return make_fixnum (PT);
26203 }
26204 }
26205 }
26206 else
26207 {
26208 if (!row->reversed_p && !row->continued_p)
26209 {
26210 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26211 w->cursor.vpos = -1;
26212 return make_fixnum (PT);
26213 }
26214 e = row->glyphs[TEXT_AREA];
26215 g = e + row->used[TEXT_AREA] - 1;
26216 for ( ; g >= e; g--)
26217 {
26218 if (BUFFERP (g->object)
26219 || (ROW_GLYPH_NEWLINE_P (row, g)
26220 && g->charpos > 0)
26221
26222
26223
26224 || g->type == STRETCH_GLYPH
26225 || (row->ends_at_zv_p
26226 && row->reversed_p
26227 && NILP (g->object)
26228 && g->type == CHAR_GLYPH
26229 && g->u.ch == ' '))
26230 {
26231 if (g->charpos > 0)
26232 SET_PT (g->charpos);
26233 else if (row->reversed_p
26234 && row->ends_at_zv_p
26235 && PT != ZV)
26236 SET_PT (ZV);
26237 else
26238 continue;
26239 w->cursor.vpos = -1;
26240 return make_fixnum (PT);
26241 }
26242 }
26243 }
26244 }
26245 }
26246
26247 simulate_display:
26248
26249
26250
26251
26252 if (b)
26253 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26254 else
26255 paragraph_dir = Qleft_to_right;
26256 if (EQ (paragraph_dir, Qright_to_left))
26257 dir = -dir;
26258 if (PT <= BEGV && dir < 0)
26259 xsignal0 (Qbeginning_of_buffer);
26260 else if (PT >= ZV && dir > 0)
26261 xsignal0 (Qend_of_buffer);
26262 else
26263 {
26264 struct text_pos pt;
26265 struct it it;
26266 int pt_x, target_x, pixel_width, pt_vpos;
26267 bool at_eol_p;
26268 bool overshoot_expected = false;
26269 bool target_is_eol_p = false;
26270 void *itdata = bidi_shelve_cache ();
26271
26272
26273 SET_TEXT_POS (pt, PT, PT_BYTE);
26274 start_display (&it, w, pt);
26275
26276
26277
26278
26279
26280
26281 if (it.line_wrap == TRUNCATE)
26282 it.last_visible_x = DISP_INFINITY;
26283
26284 if (it.cmp_it.id < 0
26285 && it.method == GET_FROM_STRING
26286 && it.area == TEXT_AREA
26287 && it.string_from_display_prop_p
26288 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26289 overshoot_expected = true;
26290
26291
26292
26293
26294
26295 reseat:
26296 reseat_at_previous_visible_line_start (&it);
26297 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26298 if (IT_CHARPOS (it) != PT)
26299 {
26300 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26301 -1, -1, -1, MOVE_TO_POS);
26302
26303
26304
26305 if (it.method == GET_FROM_DISPLAY_VECTOR
26306 && it.current.dpvec_index > 0
26307 && !overshoot_expected)
26308 {
26309 overshoot_expected = true;
26310 goto reseat;
26311 }
26312 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26313 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26314 }
26315 pt_x = it.current_x;
26316 pt_vpos = it.vpos;
26317 if (dir > 0 || overshoot_expected)
26318 {
26319 struct glyph_row *row = it.glyph_row;
26320
26321
26322
26323
26324 if (pt_x == 0)
26325 get_next_display_element (&it);
26326 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26327 it.glyph_row = NULL;
26328 PRODUCE_GLYPHS (&it);
26329 it.glyph_row = row;
26330
26331
26332
26333 it.current_x = pt_x;
26334 }
26335 else
26336 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26337 pixel_width = it.pixel_width;
26338 if (overshoot_expected && at_eol_p)
26339 pixel_width = 0;
26340 else if (pixel_width <= 0)
26341 pixel_width = 1;
26342
26343
26344
26345
26346 if (overshoot_expected)
26347 {
26348 if (it.bidi_p)
26349 pt_x += pixel_width * it.bidi_it.scan_dir;
26350 else
26351 pt_x += pixel_width;
26352 }
26353
26354
26355
26356
26357
26358
26359
26360 if (dir > 0)
26361 target_x = pt_x + pixel_width;
26362 else
26363 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26364
26365
26366
26367
26368
26369 if (dir < 0)
26370 {
26371 if (pt_x > 0)
26372 {
26373 start_display (&it, w, pt);
26374 if (it.line_wrap == TRUNCATE)
26375 it.last_visible_x = DISP_INFINITY;
26376 reseat_at_previous_visible_line_start (&it);
26377 it.current_x = it.current_y = it.hpos = 0;
26378 if (pt_vpos != 0)
26379 move_it_by_lines (&it, pt_vpos);
26380 }
26381 else
26382 {
26383 move_it_by_lines (&it, -1);
26384 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26385 target_is_eol_p = true;
26386
26387
26388
26389
26390
26391
26392
26393
26394
26395
26396 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26397 {
26398 void *it_data = NULL;
26399 struct it it2;
26400
26401 SAVE_IT (it2, it, it_data);
26402 move_it_in_display_line_to (&it, ZV, target_x,
26403 MOVE_TO_POS | MOVE_TO_X);
26404
26405
26406 if (it.current_x != target_x)
26407 target_x = it.current_x - 1;
26408 RESTORE_IT (&it, &it2, it_data);
26409 }
26410 }
26411 }
26412 else
26413 {
26414 if (at_eol_p
26415 || (target_x >= it.last_visible_x
26416 && it.line_wrap != TRUNCATE))
26417 {
26418 if (pt_x > 0)
26419 move_it_by_lines (&it, 0);
26420 move_it_by_lines (&it, 1);
26421 target_x = 0;
26422 }
26423 }
26424
26425
26426
26427
26428
26429
26430
26431 if (FRAME_WINDOW_P (it.f) && dir < 0)
26432 {
26433 struct text_pos new_pos;
26434 enum move_it_result rc = MOVE_X_REACHED;
26435
26436 if (it.current_x == 0)
26437 get_next_display_element (&it);
26438 if (it.what == IT_COMPOSITION)
26439 {
26440 new_pos.charpos = it.cmp_it.charpos;
26441 new_pos.bytepos = -1;
26442 }
26443 else
26444 new_pos = it.current.pos;
26445
26446 while (it.current_x + it.pixel_width <= target_x
26447 && (rc == MOVE_X_REACHED
26448
26449
26450
26451 || (it.line_wrap == WORD_WRAP
26452 && rc == MOVE_POS_MATCH_OR_ZV)))
26453 {
26454 int new_x = it.current_x + it.pixel_width;
26455
26456
26457
26458
26459
26460
26461
26462 if (it.what == IT_COMPOSITION)
26463 {
26464 new_pos.charpos = it.cmp_it.charpos;
26465 new_pos.bytepos = -1;
26466 }
26467 else
26468 new_pos = it.current.pos;
26469 if (new_x == it.current_x)
26470 new_x++;
26471 rc = move_it_in_display_line_to (&it, ZV, new_x,
26472 MOVE_TO_POS | MOVE_TO_X);
26473 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26474 break;
26475 }
26476
26477
26478 if (new_pos.bytepos == -1)
26479 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26480 it.current.pos = new_pos;
26481 }
26482 else if (it.current_x != target_x)
26483 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26484
26485
26486
26487 if (dir > 0)
26488 {
26489 while (IT_CHARPOS (it) == PT)
26490 {
26491 set_iterator_to_next (&it, false);
26492 if (!get_next_display_element (&it))
26493 break;
26494 }
26495 }
26496
26497
26498 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26499 bidi_unshelve_cache (itdata, false);
26500 }
26501
26502 return make_fixnum (PT);
26503
26504 #undef ROW_GLYPH_NEWLINE_P
26505 }
26506
26507 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26508 Sbidi_resolved_levels, 0, 1, 0,
26509 doc:
26510
26511
26512
26513
26514
26515
26516
26517
26518
26519
26520
26521
26522
26523
26524
26525
26526
26527
26528
26529
26530
26531
26532
26533
26534
26535 )
26536 (Lisp_Object vpos)
26537 {
26538 struct window *w = XWINDOW (selected_window);
26539 struct buffer *b = XBUFFER (w->contents);
26540 int nrow;
26541 struct glyph_row *row;
26542
26543 if (NILP (vpos))
26544 {
26545 int d1, d2, d3, d4, d5;
26546
26547 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26548 }
26549 else
26550 {
26551 CHECK_FIXNUM (vpos);
26552 nrow = XFIXNUM (vpos);
26553 }
26554
26555
26556 if (w->window_end_valid
26557 && !windows_or_buffers_changed
26558 && b
26559 && !b->clip_changed
26560 && !b->prevent_redisplay_optimizations_p
26561 && !window_outdated (w)
26562 && nrow >= 0
26563 && nrow < w->current_matrix->nrows
26564 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26565 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26566 {
26567 struct glyph *g, *e, *g1;
26568 int nglyphs, i;
26569 Lisp_Object levels;
26570
26571 if (!row->reversed_p)
26572 {
26573 g = g1 = row->glyphs[TEXT_AREA];
26574 e = g + row->used[TEXT_AREA];
26575
26576
26577
26578 while (g < e
26579 && NILP (g->object)
26580 && g->charpos < 0)
26581 g++;
26582 g1 = g;
26583
26584
26585 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26586 nglyphs++;
26587
26588
26589 levels = make_uninit_vector (nglyphs);
26590 for (i = 0; g1 < g; i++, g1++)
26591 ASET (levels, i, make_fixnum (g1->resolved_level));
26592 }
26593 else
26594 {
26595 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26596 e = row->glyphs[TEXT_AREA] - 1;
26597 while (g > e
26598 && NILP (g->object)
26599 && g->charpos < 0)
26600 g--;
26601 g1 = g;
26602 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26603 nglyphs++;
26604 levels = make_uninit_vector (nglyphs);
26605 for (i = 0; g1 > g; i++, g1--)
26606 ASET (levels, i, make_fixnum (g1->resolved_level));
26607 }
26608 return levels;
26609 }
26610 else
26611 return Qnil;
26612 }
26613
26614
26615
26616
26617
26618
26619
26620
26621
26622
26623
26624
26625
26626
26627
26628
26629
26630 static void
26631 display_menu_bar (struct window *w)
26632 {
26633 struct frame *f = XFRAME (WINDOW_FRAME (w));
26634 struct it it;
26635 Lisp_Object items;
26636 int i;
26637
26638
26639 #ifdef HAVE_NTGUI
26640 if (FRAME_W32_P (f))
26641 return;
26642 #endif
26643 #if defined (HAVE_PGTK)
26644 if (FRAME_PGTK_P (f))
26645 return;
26646 #endif
26647
26648 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26649 if (FRAME_X_P (f))
26650 return;
26651 #endif
26652
26653 #ifdef HAVE_NS
26654 if (FRAME_NS_P (f))
26655 return;
26656 #endif
26657
26658 #ifdef HAVE_HAIKU
26659 if (FRAME_HAIKU_P (f))
26660 return;
26661 #endif
26662
26663 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26664 eassert (!FRAME_WINDOW_P (f));
26665 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26666 it.first_visible_x = 0;
26667 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26668 #elif defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID)
26669 struct window *menu_window = NULL;
26670 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26671
26672 if (FRAME_WINDOW_P (f))
26673 {
26674
26675
26676 menu_window = XWINDOW (f->menu_bar_window);
26677 init_iterator (&it, menu_window, -1, -1,
26678 menu_window->desired_matrix->rows,
26679 MENU_FACE_ID);
26680 }
26681 else
26682 #endif
26683 {
26684
26685
26686 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26687 MENU_FACE_ID);
26688 it.first_visible_x = 0;
26689 it.last_visible_x = FRAME_COLS (f);
26690 }
26691
26692
26693
26694
26695 it.paragraph_embedding = L2R;
26696
26697
26698 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26699 {
26700 struct glyph_row *row = it.glyph_row + i;
26701 clear_glyph_row (row);
26702 row->enabled_p = true;
26703 row->full_width_p = true;
26704 row->reversed_p = false;
26705 }
26706
26707
26708 items = FRAME_MENU_BAR_ITEMS (it.f);
26709 for (i = 0; i < ASIZE (items); i += 4)
26710 {
26711 Lisp_Object string;
26712
26713
26714 string = AREF (items, i + 1);
26715 if (NILP (string))
26716 break;
26717
26718
26719 ASET (items, i + 3, make_fixnum (it.hpos));
26720
26721
26722 if (it.current_x < it.last_visible_x)
26723 display_string (NULL, string, Qnil, 0, 0, &it,
26724 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26725 }
26726
26727
26728 if (it.current_x < it.last_visible_x)
26729 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26730
26731
26732 compute_line_metrics (&it);
26733 it.glyph_row->full_width_p = true;
26734 it.glyph_row->continued_p = false;
26735 it.glyph_row->truncated_on_left_p = false;
26736 it.glyph_row->truncated_on_right_p = false;
26737
26738
26739
26740
26741
26742 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
26743
26744 extend_face_to_end_of_line (&it);
26745 if (face->box != FACE_NO_BOX)
26746 {
26747 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26748 + it.glyph_row->used[TEXT_AREA] - 1);
26749 int box_thickness = face->box_vertical_line_width;
26750 last->right_box_line_p = true;
26751
26752
26753
26754
26755
26756
26757 if (box_thickness > 0)
26758 last->pixel_width += max (0, (box_thickness
26759 - (it.current_x - it.last_visible_x)));
26760 }
26761
26762
26763
26764 if (FRAME_WINDOW_P (it.f) && menu_window)
26765 {
26766 struct glyph_row *row;
26767 int delta_height;
26768
26769 row = it.glyph_row;
26770 delta_height
26771 = ((row->y + row->height)
26772 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26773
26774 if (delta_height != 0)
26775 {
26776 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26777 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26778 }
26779 }
26780 #endif
26781 }
26782
26783
26784
26785
26786 #ifndef HAVE_ANDROID
26787
26788
26789 static void
26790 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26791 {
26792 struct glyph *pointers[1 + LAST_AREA];
26793 int to_used = to->used[TEXT_AREA];
26794
26795
26796 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26797
26798
26799 *to = *from;
26800
26801
26802 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26803
26804
26805 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26806 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26807
26808
26809
26810 if (to_used > from->used[TEXT_AREA])
26811 fill_up_frame_row_with_spaces (to, to_used);
26812 }
26813
26814
26815
26816
26817
26818
26819
26820
26821
26822
26823
26824
26825
26826
26827
26828
26829
26830
26831
26832
26833
26834
26835 void
26836 display_tty_menu_item (const char *item_text, int width, int face_id,
26837 int x, int y, bool submenu)
26838 {
26839 struct it it;
26840 struct frame *f = SELECTED_FRAME ();
26841 struct window *w = XWINDOW (f->selected_window);
26842 struct glyph_row *row;
26843 size_t item_len = strlen (item_text);
26844
26845 eassert (FRAME_TERMCAP_P (f));
26846
26847
26848
26849
26850
26851
26852 if (y >= f->desired_matrix->nrows)
26853 return;
26854
26855 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26856 it.first_visible_x = 0;
26857 it.last_visible_x = FRAME_COLS (f) - 1;
26858 row = it.glyph_row;
26859
26860 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26861 bool saved_width = row->full_width_p;
26862 row->full_width_p = true;
26863 bool saved_reversed = row->reversed_p;
26864 row->reversed_p = false;
26865 row->enabled_p = true;
26866
26867
26868
26869 eassert (x < f->desired_matrix->matrix_w);
26870 it.current_x = it.hpos = x;
26871 it.current_y = it.vpos = y;
26872 int saved_used = row->used[TEXT_AREA];
26873 bool saved_truncated = row->truncated_on_right_p;
26874 row->used[TEXT_AREA] = x;
26875 it.face_id = face_id;
26876 it.line_wrap = TRUNCATE;
26877
26878
26879
26880
26881
26882
26883 it.paragraph_embedding = L2R;
26884
26885
26886 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26887 width--;
26888
26889 if (submenu)
26890 {
26891 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26892 item_len, 0, FRAME_COLS (f) - 1, -1);
26893 width -= item_len;
26894
26895 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26896 FRAME_COLS (f) - 1, -1);
26897 }
26898 else
26899 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26900 width, 0, FRAME_COLS (f) - 1, -1);
26901
26902 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26903 row->truncated_on_right_p = saved_truncated;
26904 row->hash = row_hash (row);
26905 row->full_width_p = saved_width;
26906 row->reversed_p = saved_reversed;
26907 }
26908
26909 #endif
26910
26911
26912
26913
26914
26915
26916
26917
26918
26919
26920
26921 static int
26922 redisplay_mode_lines (Lisp_Object window, bool force)
26923 {
26924 int nwindows = 0;
26925
26926 while (!NILP (window))
26927 {
26928 struct window *w = XWINDOW (window);
26929
26930 if (WINDOWP (w->contents))
26931 nwindows += redisplay_mode_lines (w->contents, force);
26932 else if (force
26933 || FRAME_GARBAGED_P (XFRAME (w->frame))
26934 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26935 {
26936 struct text_pos lpoint;
26937 struct buffer *old = current_buffer;
26938
26939
26940 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26941 set_buffer_internal_1 (XBUFFER (w->contents));
26942
26943
26944
26945 if (!EQ (window, selected_window))
26946 {
26947 struct text_pos pt;
26948
26949 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26950 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26951 }
26952
26953
26954 clear_glyph_matrix (w->desired_matrix);
26955 if (display_mode_lines (w))
26956 ++nwindows;
26957
26958
26959 set_buffer_internal_1 (old);
26960 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26961 }
26962
26963 window = w->next;
26964 }
26965
26966 return nwindows;
26967 }
26968
26969
26970
26971
26972
26973
26974 static int
26975 display_mode_lines (struct window *w)
26976 {
26977 Lisp_Object old_selected_window = selected_window;
26978 Lisp_Object new_frame = w->frame;
26979 specpdl_ref count = SPECPDL_INDEX ();
26980 int n = 0;
26981
26982 record_unwind_protect (restore_selected_window, selected_window);
26983 record_unwind_protect
26984 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
26985
26986 if (window_wants_mode_line (w))
26987 {
26988 Lisp_Object window;
26989 Lisp_Object default_help
26990 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
26991
26992
26993
26994 XSETWINDOW (window, w);
26995 if (FUNCTIONP (default_help))
26996 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
26997 else if (STRINGP (default_help))
26998 wset_mode_line_help_echo (w, default_help);
26999 else
27000 wset_mode_line_help_echo (w, Qnil);
27001 }
27002
27003 selected_frame = new_frame;
27004
27005
27006 XSETWINDOW (selected_window, w);
27007 XFRAME (new_frame)->selected_window = selected_window;
27008
27009
27010 line_number_displayed = false;
27011 w->column_number_displayed = -1;
27012
27013 if (window_wants_mode_line (w))
27014 {
27015 Lisp_Object window_mode_line_format
27016 = window_parameter (w, Qmode_line_format);
27017 struct window *sel_w = XWINDOW (old_selected_window);
27018
27019
27020 display_mode_line (w,
27021 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
27022 NILP (window_mode_line_format)
27023 ? BVAR (current_buffer, mode_line_format)
27024 : window_mode_line_format);
27025 ++n;
27026 }
27027
27028 if (window_wants_tab_line (w))
27029 {
27030 Lisp_Object window_tab_line_format
27031 = window_parameter (w, Qtab_line_format);
27032
27033 display_mode_line (w, TAB_LINE_FACE_ID,
27034 NILP (window_tab_line_format)
27035 ? BVAR (current_buffer, tab_line_format)
27036 : window_tab_line_format);
27037 ++n;
27038 }
27039
27040 if (window_wants_header_line (w))
27041 {
27042 Lisp_Object window_header_line_format
27043 = window_parameter (w, Qheader_line_format);
27044
27045 display_mode_line (w, HEADER_LINE_FACE_ID,
27046 NILP (window_header_line_format)
27047 ? BVAR (current_buffer, header_line_format)
27048 : window_header_line_format);
27049 ++n;
27050 }
27051
27052 unbind_to (count, Qnil);
27053
27054 if (n > 0)
27055 w->must_be_updated_p = true;
27056 return n;
27057 }
27058
27059
27060
27061
27062
27063
27064
27065
27066 static int
27067 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
27068 {
27069 struct it it;
27070 struct face *face;
27071 specpdl_ref count = SPECPDL_INDEX ();
27072
27073 init_iterator (&it, w, -1, -1, NULL, face_id);
27074
27075
27076 it.glyph_row->enabled_p = false;
27077 prepare_desired_row (w, it.glyph_row, true);
27078
27079 it.glyph_row->mode_line_p = true;
27080 if (face_id == TAB_LINE_FACE_ID)
27081 {
27082 it.glyph_row->tab_line_p = true;
27083 w->desired_matrix->tab_line_p = true;
27084 }
27085 else if (face_id == HEADER_LINE_FACE_ID)
27086 w->desired_matrix->header_line_p = true;
27087
27088
27089
27090
27091 it.paragraph_embedding = L2R;
27092
27093 record_unwind_protect (unwind_format_mode_line,
27094 format_mode_line_unwind_data (NULL, NULL,
27095 Qnil, false));
27096
27097
27098
27099
27100 push_kboard (FRAME_KBOARD (it.f));
27101 record_unwind_save_match_data ();
27102
27103 if (NILP (Vmode_line_compact)
27104 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
27105 {
27106 mode_line_target = MODE_LINE_DISPLAY;
27107 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27108 }
27109 else
27110 {
27111 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
27112 if (EQ (Vmode_line_compact, Qlong)
27113 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
27114 {
27115
27116
27117 display_string (NULL, mode_string, Qnil,
27118 0, 0, &it, 0, 0, 0,
27119 STRING_MULTIBYTE (mode_string));
27120 }
27121 else
27122 {
27123
27124 ptrdiff_t i = 0, i_byte = 0, start = 0;
27125 int prev = 0;
27126
27127 while (i < SCHARS (mode_string))
27128 {
27129 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
27130 if (c == ' ' && prev == ' ')
27131 {
27132 display_string (NULL,
27133 Fsubstring (mode_string, make_fixnum (start),
27134 make_fixnum (i - 1)),
27135 Qnil, 0, 0, &it, 0, 0, 0,
27136 STRING_MULTIBYTE (mode_string));
27137
27138 while (c == ' ' && i < SCHARS (mode_string))
27139 c = fetch_string_char_advance (mode_string, &i, &i_byte);
27140 start = i - 1;
27141 }
27142 prev = c;
27143 }
27144
27145
27146 if (start < i)
27147 display_string (NULL,
27148 Fsubstring (mode_string, make_fixnum (start),
27149 make_fixnum (i)),
27150 Qnil, 0, 0, &it, 0, 0, 0,
27151 STRING_MULTIBYTE (mode_string));
27152 }
27153 }
27154 pop_kboard ();
27155
27156 unbind_to (count, Qnil);
27157
27158
27159 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
27160
27161 compute_line_metrics (&it);
27162 it.glyph_row->full_width_p = true;
27163 it.glyph_row->continued_p = false;
27164 it.glyph_row->truncated_on_left_p = false;
27165 it.glyph_row->truncated_on_right_p = false;
27166
27167
27168 face = FACE_FROM_ID (it.f, face_id);
27169 extend_face_to_end_of_line (&it);
27170 if (face->box != FACE_NO_BOX)
27171 {
27172 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
27173 + it.glyph_row->used[TEXT_AREA] - 1);
27174 int box_thickness = face->box_vertical_line_width;
27175 last->right_box_line_p = true;
27176
27177
27178
27179
27180
27181
27182 if (box_thickness > 0)
27183 last->pixel_width += max (0, (box_thickness
27184 - (it.current_x - it.last_visible_x)));
27185 }
27186
27187 return it.glyph_row->height;
27188 }
27189
27190
27191
27192
27193 static Lisp_Object
27194 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
27195 {
27196 register Lisp_Object tail, prev;
27197 register Lisp_Object tem;
27198
27199 tail = list;
27200 prev = Qnil;
27201 while (CONSP (tail))
27202 {
27203 tem = XCAR (tail);
27204
27205 if (EQ (elt, tem))
27206 {
27207
27208 if (NILP (prev))
27209 list = XCDR (tail);
27210 else
27211 Fsetcdr (prev, XCDR (tail));
27212
27213
27214 Fsetcdr (tail, list);
27215 return tail;
27216 }
27217 else
27218 prev = tail;
27219 tail = XCDR (tail);
27220 maybe_quit ();
27221 }
27222
27223
27224 return list;
27225 }
27226
27227
27228
27229
27230
27231 static Lisp_Object
27232 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27233 {
27234 eassert (nargs == 4);
27235 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27236 }
27237
27238
27239
27240
27241
27242
27243
27244
27245
27246
27247
27248
27249
27250
27251
27252
27253
27254
27255
27256
27257
27258
27259
27260
27261
27262 static int
27263 display_mode_element (struct it *it, int depth, int field_width, int precision,
27264 Lisp_Object elt, Lisp_Object props, bool risky)
27265 {
27266 int n = 0, field, prec;
27267 bool literal = false;
27268
27269 tail_recurse:
27270 if (depth > 100)
27271 elt = build_string ("*too-deep*");
27272
27273 depth++;
27274
27275 switch (XTYPE (elt))
27276 {
27277 case Lisp_String:
27278 {
27279
27280 unsigned char c;
27281 ptrdiff_t offset = 0;
27282
27283 if (SCHARS (elt) > 0
27284 && (!NILP (props) || risky))
27285 {
27286 Lisp_Object oprops, aelt;
27287 oprops = Ftext_properties_at (make_fixnum (0), elt);
27288
27289
27290
27291
27292
27293 if (NILP (Fequal (props, oprops)) || risky)
27294 {
27295
27296
27297 if (! NILP (oprops) && !risky)
27298 {
27299 Lisp_Object tem;
27300
27301 oprops = Fcopy_sequence (oprops);
27302 tem = props;
27303 while (CONSP (tem))
27304 {
27305 oprops = plist_put (oprops, XCAR (tem),
27306 XCAR (XCDR (tem)));
27307 tem = XCDR (XCDR (tem));
27308 }
27309 props = oprops;
27310 }
27311
27312 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27313 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27314 {
27315
27316
27317 elt = XCAR (aelt);
27318 mode_line_proptrans_alist
27319 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27320 }
27321 else
27322 {
27323 Lisp_Object tem;
27324
27325
27326
27327 if (! NILP (aelt))
27328 mode_line_proptrans_alist
27329 = Fdelq (aelt, mode_line_proptrans_alist);
27330
27331 elt = Fcopy_sequence (elt);
27332
27333
27334
27335 internal_condition_case_n (safe_set_text_properties,
27336 4,
27337 ((Lisp_Object [])
27338 {make_fixnum (0),
27339 Flength (elt),
27340 props,
27341 elt}),
27342 Qt, safe_eval_handler);
27343
27344 mode_line_proptrans_alist
27345 = Fcons (Fcons (elt, props),
27346 mode_line_proptrans_alist);
27347
27348
27349 tem = Fnthcdr (make_fixnum (50),
27350 mode_line_proptrans_alist);
27351 if (! NILP (tem))
27352 XSETCDR (tem, Qnil);
27353 }
27354 }
27355 }
27356
27357 offset = 0;
27358
27359 if (literal)
27360 {
27361 prec = precision - n;
27362 switch (mode_line_target)
27363 {
27364 case MODE_LINE_NOPROP:
27365 case MODE_LINE_TITLE:
27366 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27367 break;
27368 case MODE_LINE_STRING:
27369 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27370 break;
27371 case MODE_LINE_DISPLAY:
27372 n += display_string (NULL, elt, Qnil, 0, 0, it,
27373 0, prec, 0, STRING_MULTIBYTE (elt));
27374 break;
27375 }
27376
27377 break;
27378 }
27379
27380
27381
27382 while ((precision <= 0 || n < precision)
27383 && SREF (elt, offset) != 0
27384 && (mode_line_target != MODE_LINE_DISPLAY
27385 || it->current_x < it->last_visible_x))
27386 {
27387 ptrdiff_t last_offset = offset;
27388
27389
27390 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27391 ;
27392
27393 if (offset - 1 != last_offset)
27394 {
27395 ptrdiff_t nchars, nbytes;
27396
27397
27398
27399
27400 offset--;
27401
27402 prec = c_string_width (SDATA (elt) + last_offset,
27403 offset - last_offset, precision - n,
27404 &nchars, &nbytes);
27405
27406 switch (mode_line_target)
27407 {
27408 case MODE_LINE_NOPROP:
27409 case MODE_LINE_TITLE:
27410 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27411 break;
27412 case MODE_LINE_STRING:
27413 {
27414 ptrdiff_t bytepos = last_offset;
27415 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27416 ptrdiff_t endpos = (precision <= 0
27417 ? string_byte_to_char (elt, offset)
27418 : charpos + nchars);
27419 Lisp_Object mode_string
27420 = Fsubstring (elt, make_fixnum (charpos),
27421 make_fixnum (endpos));
27422 n += store_mode_line_string (NULL, mode_string, false,
27423 0, 0, Qnil);
27424 }
27425 break;
27426 case MODE_LINE_DISPLAY:
27427 {
27428 ptrdiff_t bytepos = last_offset;
27429 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27430
27431 if (precision <= 0)
27432 nchars = string_byte_to_char (elt, offset) - charpos;
27433 n += display_string (NULL, elt, Qnil, 0, charpos,
27434 it, 0, nchars, 0,
27435 STRING_MULTIBYTE (elt));
27436 }
27437 break;
27438 }
27439 }
27440 else
27441 {
27442 ptrdiff_t percent_position = offset;
27443
27444
27445
27446 field = 0;
27447 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27448 field = field * 10 + c - '0';
27449
27450
27451 if (field_width - n > 0 && field > field_width - n)
27452 field = field_width - n;
27453
27454
27455 prec = precision - n;
27456
27457 if (c == 'M')
27458 n += display_mode_element (it, depth, field, prec,
27459 Vglobal_mode_string, props,
27460 risky);
27461 else if (c != 0)
27462 {
27463 bool multibyte;
27464 ptrdiff_t bytepos, charpos;
27465 const char *spec;
27466 Lisp_Object string;
27467
27468 bytepos = percent_position;
27469 charpos = (STRING_MULTIBYTE (elt)
27470 ? string_byte_to_char (elt, bytepos)
27471 : bytepos);
27472 spec = decode_mode_spec (it->w, c, field, &string);
27473 eassert (NILP (string) || STRINGP (string));
27474 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27475
27476
27477 ptrdiff_t nbytes = strlen (spec);
27478 ptrdiff_t nchars, mb_nbytes;
27479 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27480 &nchars, &mb_nbytes);
27481 if (!(nbytes == nchars || nbytes != mb_nbytes))
27482 multibyte = true;
27483
27484 switch (mode_line_target)
27485 {
27486 case MODE_LINE_NOPROP:
27487 case MODE_LINE_TITLE:
27488 n += store_mode_line_noprop (spec, field, prec);
27489 break;
27490 case MODE_LINE_STRING:
27491 {
27492 Lisp_Object tem = build_string (spec);
27493 props = Ftext_properties_at (make_fixnum (charpos), elt);
27494
27495 n += store_mode_line_string (NULL, tem, false,
27496 field, prec, props);
27497 }
27498 break;
27499 case MODE_LINE_DISPLAY:
27500 {
27501 int nglyphs_before, nwritten;
27502
27503 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27504 nwritten = display_string (spec, string, elt,
27505 charpos, 0, it,
27506 field, prec, 0,
27507 multibyte);
27508
27509
27510
27511
27512 if (nwritten > 0)
27513 {
27514 struct glyph *glyph
27515 = (it->glyph_row->glyphs[TEXT_AREA]
27516 + nglyphs_before);
27517 int i;
27518
27519 for (i = 0; i < nwritten; ++i)
27520 {
27521 glyph[i].object = elt;
27522 glyph[i].charpos = charpos;
27523 }
27524
27525 n += nwritten;
27526 }
27527 }
27528 break;
27529 }
27530 }
27531 else
27532 break;
27533 }
27534 }
27535 }
27536 break;
27537
27538 case Lisp_Symbol:
27539
27540
27541
27542
27543 {
27544 register Lisp_Object tem;
27545
27546
27547
27548 if (NILP (Fget (elt, Qrisky_local_variable)))
27549 risky = true;
27550
27551 tem = Fboundp (elt);
27552 if (!NILP (tem))
27553 {
27554 tem = Fsymbol_value (elt);
27555
27556
27557 if (STRINGP (tem))
27558 literal = true;
27559
27560 if (!EQ (tem, elt))
27561 {
27562
27563 elt = tem;
27564 goto tail_recurse;
27565 }
27566 }
27567 }
27568 break;
27569
27570 case Lisp_Cons:
27571 {
27572 register Lisp_Object car, tem;
27573
27574
27575
27576
27577
27578
27579
27580
27581
27582
27583 car = XCAR (elt);
27584 if (EQ (car, QCeval))
27585 {
27586
27587
27588
27589 if (risky)
27590 break;
27591
27592 if (CONSP (XCDR (elt)))
27593 {
27594 Lisp_Object spec;
27595 spec = safe__eval (true, XCAR (XCDR (elt)));
27596
27597
27598
27599
27600
27601
27602 if (!FRAME_LIVE_P (it->f))
27603 signal_error (":eval deleted the frame being displayed", elt);
27604 n += display_mode_element (it, depth, field_width - n,
27605 precision - n, spec, props,
27606 risky);
27607 }
27608 }
27609 else if (EQ (car, QCpropertize))
27610 {
27611
27612
27613
27614 if (risky)
27615 break;
27616
27617 if (CONSP (XCDR (elt)))
27618 n += display_mode_element (it, depth, field_width - n,
27619 precision - n, XCAR (XCDR (elt)),
27620 XCDR (XCDR (elt)), risky);
27621 }
27622 else if (SYMBOLP (car))
27623 {
27624 tem = Fboundp (car);
27625 elt = XCDR (elt);
27626 if (!CONSP (elt))
27627 goto invalid;
27628
27629
27630 if (!NILP (tem))
27631 {
27632 tem = Fsymbol_value (car);
27633 if (!NILP (tem))
27634 {
27635 elt = XCAR (elt);
27636 goto tail_recurse;
27637 }
27638 }
27639
27640
27641
27642 elt = XCDR (elt);
27643 if (NILP (elt))
27644 break;
27645 else if (!CONSP (elt))
27646 goto invalid;
27647 elt = XCAR (elt);
27648 goto tail_recurse;
27649 }
27650 else if (FIXNUMP (car))
27651 {
27652 register int lim = XFIXNUM (car);
27653 elt = XCDR (elt);
27654 if (lim < 0)
27655 {
27656
27657 if (precision <= 0)
27658 precision = -lim;
27659 else
27660 precision = min (precision, -lim);
27661 }
27662 else if (lim > 0)
27663 {
27664
27665
27666 if (precision > 0)
27667 lim = min (precision, lim);
27668
27669
27670
27671
27672 field_width = max (lim, field_width);
27673 }
27674 goto tail_recurse;
27675 }
27676 else if (STRINGP (car) || CONSP (car))
27677 FOR_EACH_TAIL_SAFE (elt)
27678 {
27679 if (0 < precision && precision <= n)
27680 break;
27681 n += display_mode_element (it, depth,
27682
27683
27684 (! CONSP (XCDR (elt))
27685 ? field_width - n
27686 : 0),
27687 precision - n, XCAR (elt),
27688 props, risky);
27689 }
27690 }
27691 break;
27692
27693 default:
27694 invalid:
27695 elt = build_string ("*invalid*");
27696 goto tail_recurse;
27697 }
27698
27699
27700 if (field_width > 0 && n < field_width)
27701 {
27702 switch (mode_line_target)
27703 {
27704 case MODE_LINE_NOPROP:
27705 case MODE_LINE_TITLE:
27706 n += store_mode_line_noprop ("", field_width - n, 0);
27707 break;
27708 case MODE_LINE_STRING:
27709 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27710 Qnil);
27711 break;
27712 case MODE_LINE_DISPLAY:
27713 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27714 0, 0, 0);
27715 break;
27716 }
27717 }
27718
27719 return n;
27720 }
27721
27722
27723
27724
27725
27726
27727
27728
27729
27730
27731
27732
27733
27734
27735
27736
27737
27738
27739
27740
27741 static int
27742 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27743 bool copy_string,
27744 int field_width, int precision, Lisp_Object props)
27745 {
27746 ptrdiff_t len;
27747 int n = 0;
27748
27749 if (string != NULL)
27750 {
27751 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27752 lisp_string = make_string (string, len);
27753 if (NILP (props))
27754 props = mode_line_string_face_prop;
27755 else if (!NILP (mode_line_string_face))
27756 {
27757 Lisp_Object face = plist_get (props, Qface);
27758 props = Fcopy_sequence (props);
27759 if (NILP (face))
27760 face = mode_line_string_face;
27761 else
27762 face = list2 (face, mode_line_string_face);
27763 props = plist_put (props, Qface, face);
27764 }
27765 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27766 props, lisp_string);
27767 }
27768 else
27769 {
27770 len = SCHARS (lisp_string);
27771 if (precision > 0 && len > precision)
27772 {
27773 len = precision;
27774 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27775 precision = -1;
27776 }
27777 if (!NILP (mode_line_string_face))
27778 {
27779 Lisp_Object face;
27780 if (NILP (props))
27781 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27782 face = plist_get (props, Qface);
27783 if (NILP (face))
27784 face = mode_line_string_face;
27785 else
27786 face = list2 (face, mode_line_string_face);
27787 props = list2 (Qface, face);
27788 if (copy_string)
27789 lisp_string = Fcopy_sequence (lisp_string);
27790 }
27791 if (!NILP (props))
27792 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27793 props, lisp_string);
27794 }
27795
27796 if (len > 0)
27797 {
27798 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27799 n += len;
27800 }
27801
27802 if (field_width > len)
27803 {
27804 field_width -= len;
27805 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27806 Qnil);
27807 if (!NILP (props))
27808 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27809 props, lisp_string);
27810 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27811 n += field_width;
27812 }
27813
27814 return n;
27815 }
27816
27817
27818 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27819 1, 4, 0,
27820 doc:
27821
27822
27823
27824
27825
27826
27827
27828
27829
27830
27831
27832
27833
27834
27835
27836 )
27837 (Lisp_Object format, Lisp_Object face,
27838 Lisp_Object window, Lisp_Object buffer)
27839 {
27840 struct it it;
27841 int len;
27842 struct window *w;
27843 struct buffer *old_buffer = NULL;
27844 int face_id;
27845 bool no_props = FIXNUMP (face);
27846 specpdl_ref count = SPECPDL_INDEX ();
27847 Lisp_Object str;
27848 int string_start = 0;
27849
27850 w = decode_any_window (window);
27851 XSETWINDOW (window, w);
27852
27853 if (NILP (buffer))
27854 buffer = w->contents;
27855 CHECK_BUFFER (buffer);
27856
27857
27858
27859 if (NILP (format) || noninteractive)
27860 return empty_unibyte_string;
27861
27862 if (no_props)
27863 face = Qnil;
27864
27865 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27866 : EQ (face, Qt) ? (EQ (window, selected_window)
27867 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27868 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27869 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27870 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27871 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27872 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27873 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27874 : DEFAULT_FACE_ID;
27875
27876 old_buffer = current_buffer;
27877
27878
27879
27880 record_unwind_protect (unwind_format_mode_line,
27881 format_mode_line_unwind_data
27882 (XFRAME (WINDOW_FRAME (w)),
27883 old_buffer, selected_window, true));
27884 mode_line_proptrans_alist = Qnil;
27885
27886 Fselect_window (window, Qt);
27887 set_buffer_internal_1 (XBUFFER (buffer));
27888
27889 init_iterator (&it, w, -1, -1, NULL, face_id);
27890
27891 if (no_props)
27892 {
27893 mode_line_target = MODE_LINE_NOPROP;
27894 mode_line_string_face_prop = Qnil;
27895 mode_line_string_list = Qnil;
27896 string_start = MODE_LINE_NOPROP_LEN (0);
27897 }
27898 else
27899 {
27900 mode_line_target = MODE_LINE_STRING;
27901 mode_line_string_list = Qnil;
27902 mode_line_string_face = face;
27903 mode_line_string_face_prop
27904 = NILP (face) ? Qnil : list2 (Qface, face);
27905 }
27906
27907 push_kboard (FRAME_KBOARD (it.f));
27908 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27909 pop_kboard ();
27910
27911 if (no_props)
27912 {
27913 len = MODE_LINE_NOPROP_LEN (string_start);
27914 str = make_string (mode_line_noprop_buf + string_start, len);
27915 }
27916 else
27917 {
27918 mode_line_string_list = Fnreverse (mode_line_string_list);
27919 str = Fmapconcat (Qidentity, mode_line_string_list,
27920 empty_unibyte_string);
27921 }
27922
27923 return unbind_to (count, str);
27924 }
27925
27926
27927
27928
27929 static void
27930 pint2str (register char *buf, register int width, register ptrdiff_t d)
27931 {
27932 register char *p = buf;
27933
27934 if (d <= 0)
27935 *p++ = '0';
27936 else
27937 {
27938 while (d > 0)
27939 {
27940 *p++ = d % 10 + '0';
27941 d /= 10;
27942 }
27943 }
27944
27945 for (width -= (int) (p - buf); width > 0; --width)
27946 *p++ = ' ';
27947 *p-- = '\0';
27948 while (p > buf)
27949 {
27950 d = *buf;
27951 *buf++ = *p;
27952 *p-- = d;
27953 }
27954 }
27955
27956
27957
27958
27959
27960 static const char power_letter[] =
27961 {
27962 0,
27963 'k',
27964 'M',
27965 'G',
27966 'T',
27967 'P',
27968 'E',
27969 'Z',
27970 'Y',
27971 'R',
27972 'Q'
27973 };
27974
27975 static void
27976 pint2hrstr (char *buf, int width, ptrdiff_t d)
27977 {
27978
27979
27980 ptrdiff_t quotient = d;
27981 int remainder = 0;
27982
27983 int tenths = -1;
27984 int exponent = 0;
27985
27986
27987 int length;
27988
27989 char * psuffix;
27990 char * p;
27991
27992 if (quotient >= 1000)
27993 {
27994
27995 do
27996 {
27997 remainder = quotient % 1000;
27998 quotient /= 1000;
27999 exponent++;
28000 }
28001 while (quotient >= 1000);
28002
28003
28004 if (quotient <= 9)
28005 {
28006 tenths = remainder / 100;
28007 if (remainder % 100 >= 50)
28008 {
28009 if (tenths < 9)
28010 tenths++;
28011 else
28012 {
28013 quotient++;
28014 if (quotient == 10)
28015 tenths = -1;
28016 else
28017 tenths = 0;
28018 }
28019 }
28020 }
28021 else
28022 if (remainder >= 500)
28023 {
28024 if (quotient < 999)
28025 quotient++;
28026 else
28027 {
28028 quotient = 1;
28029 exponent++;
28030 tenths = 0;
28031 }
28032 }
28033 }
28034
28035
28036 if (tenths == -1 && quotient <= 99)
28037 if (quotient <= 9)
28038 length = 1;
28039 else
28040 length = 2;
28041 else
28042 length = 3;
28043 p = psuffix = buf + max (width, length);
28044
28045
28046 *psuffix++ = power_letter[exponent];
28047 *psuffix = '\0';
28048
28049
28050 if (tenths >= 0)
28051 {
28052 *--p = '0' + tenths;
28053 *--p = '.';
28054 }
28055
28056
28057 do
28058 {
28059 int digit = quotient % 10;
28060 *--p = '0' + digit;
28061 }
28062 while ((quotient /= 10) != 0);
28063
28064
28065 while (buf < p)
28066 *--p = ' ';
28067 }
28068
28069
28070
28071
28072
28073 static unsigned char invalid_eol_type[] = "(*invalid*)";
28074
28075 static char *
28076 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
28077 {
28078 Lisp_Object val;
28079 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
28080 const unsigned char *eol_str;
28081 int eol_str_len;
28082
28083 Lisp_Object eoltype;
28084
28085 val = CODING_SYSTEM_SPEC (coding_system);
28086 eoltype = Qnil;
28087
28088 if (!VECTORP (val))
28089 {
28090 *buf++ = multibyte ? '-' : ' ';
28091 if (eol_flag)
28092 eoltype = eol_mnemonic_undecided;
28093
28094 }
28095 else
28096 {
28097 Lisp_Object attrs;
28098 Lisp_Object eolvalue;
28099
28100 attrs = AREF (val, 0);
28101 eolvalue = AREF (val, 2);
28102
28103 if (multibyte)
28104 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
28105 (unsigned char *) buf);
28106 else
28107 *buf++ = ' ';
28108
28109 if (eol_flag)
28110 {
28111
28112
28113 if (NILP (eolvalue))
28114 eoltype = eol_mnemonic_undecided;
28115 else if (VECTORP (eolvalue))
28116 eoltype = eol_mnemonic_undecided;
28117 else
28118 eoltype = (EQ (eolvalue, Qunix)
28119 ? eol_mnemonic_unix
28120 : EQ (eolvalue, Qdos)
28121 ? eol_mnemonic_dos : eol_mnemonic_mac);
28122 }
28123 }
28124
28125 if (eol_flag)
28126 {
28127
28128 if (STRINGP (eoltype))
28129 {
28130 eol_str = SDATA (eoltype);
28131 eol_str_len = SBYTES (eoltype);
28132 }
28133 else if (CHARACTERP (eoltype))
28134 {
28135 int c = XFIXNAT (eoltype);
28136 return buf + CHAR_STRING (c, (unsigned char *) buf);
28137 }
28138 else
28139 {
28140 eol_str = invalid_eol_type;
28141 eol_str_len = sizeof (invalid_eol_type) - 1;
28142 }
28143 memcpy (buf, eol_str, eol_str_len);
28144 buf += eol_str_len;
28145 }
28146
28147 return buf;
28148 }
28149
28150
28151
28152
28153 static int
28154 percent99 (ptrdiff_t n, ptrdiff_t d)
28155 {
28156 int percent = (d - 1 + 100.0 * n) / d;
28157 return min (percent, 99);
28158 }
28159
28160
28161
28162
28163
28164
28165
28166
28167
28168 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
28169
28170 static const char *
28171 decode_mode_spec (struct window *w, register int c, int field_width,
28172 Lisp_Object *string)
28173 {
28174 Lisp_Object obj;
28175 struct frame *f = XFRAME (WINDOW_FRAME (w));
28176 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
28177
28178
28179
28180
28181
28182 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
28183 struct buffer *b = current_buffer;
28184
28185 obj = Qnil;
28186 *string = Qnil;
28187
28188 switch (c)
28189 {
28190 case '*':
28191 if (!NILP (BVAR (b, read_only)))
28192 return "%";
28193 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28194 return "*";
28195 return "-";
28196
28197 case '+':
28198
28199 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28200 return "*";
28201 if (!NILP (BVAR (b, read_only)))
28202 return "%";
28203 return "-";
28204
28205 case '&':
28206
28207 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28208 return "*";
28209 return "-";
28210
28211 case '%':
28212 return "%";
28213
28214 case '[':
28215 {
28216 int i;
28217 char *p;
28218
28219 if (command_loop_level > 5)
28220 return "[[[... ";
28221 p = decode_mode_spec_buf;
28222 for (i = 0; i < command_loop_level; i++)
28223 *p++ = '[';
28224 *p = 0;
28225 return decode_mode_spec_buf;
28226 }
28227
28228 case ']':
28229 {
28230 int i;
28231 char *p;
28232
28233 if (command_loop_level > 5)
28234 return " ...]]]";
28235 p = decode_mode_spec_buf;
28236 for (i = 0; i < command_loop_level; i++)
28237 *p++ = ']';
28238 *p = 0;
28239 return decode_mode_spec_buf;
28240 }
28241
28242 case '-':
28243 {
28244 register int i;
28245
28246
28247 if (mode_line_target == MODE_LINE_NOPROP
28248 || mode_line_target == MODE_LINE_STRING)
28249 return "--";
28250 if (field_width <= 0
28251 || field_width > sizeof (lots_of_dashes))
28252 {
28253 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28254 decode_mode_spec_buf[i] = '-';
28255 decode_mode_spec_buf[i] = '\0';
28256 return decode_mode_spec_buf;
28257 }
28258 else
28259 return lots_of_dashes;
28260 }
28261
28262 case 'b':
28263 obj = BVAR (b, name);
28264 break;
28265
28266 case 'c':
28267 case 'C':
28268
28269
28270
28271
28272
28273 if (mode_line_target == MODE_LINE_TITLE)
28274 return "";
28275 else
28276 {
28277 ptrdiff_t col = current_column ();
28278 int disp_col = (c == 'C') ? col + 1 : col;
28279 w->column_number_displayed = col;
28280 pint2str (decode_mode_spec_buf, width, disp_col);
28281 return decode_mode_spec_buf;
28282 }
28283
28284 case 'e':
28285 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28286 {
28287 if (NILP (Vmemory_full))
28288 return "";
28289 else
28290 return "!MEM FULL! ";
28291 }
28292 #else
28293 return "";
28294 #endif
28295
28296 case 'F':
28297
28298 if (!NILP (f->title))
28299 return SSDATA (f->title);
28300 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28301 return SSDATA (f->name);
28302 return "Emacs";
28303
28304 case 'f':
28305 obj = BVAR (b, filename);
28306 break;
28307
28308 case 'i':
28309 {
28310 ptrdiff_t size = ZV - BEGV;
28311 pint2str (decode_mode_spec_buf, width, size);
28312 return decode_mode_spec_buf;
28313 }
28314
28315 case 'I':
28316 {
28317 ptrdiff_t size = ZV - BEGV;
28318 pint2hrstr (decode_mode_spec_buf, width, size);
28319 return decode_mode_spec_buf;
28320 }
28321
28322 case 'l':
28323 {
28324 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28325 ptrdiff_t topline, nlines, height;
28326 ptrdiff_t junk;
28327
28328
28329 if (mode_line_target == MODE_LINE_TITLE)
28330 return "";
28331
28332 startpos = marker_position (w->start);
28333 startpos_byte = marker_byte_position (w->start);
28334 height = WINDOW_TOTAL_LINES (w);
28335
28336
28337
28338
28339
28340
28341
28342
28343 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28344 && startpos_byte <= BUF_ZV_BYTE (b)))
28345 {
28346 startpos = BUF_BEGV (b);
28347 startpos_byte = BUF_BEGV_BYTE (b);
28348 w->base_line_pos = 0;
28349 w->base_line_number = 0;
28350 }
28351
28352
28353
28354 if (w->base_line_pos == -1)
28355 goto no_value;
28356
28357
28358 if (FIXNUMP (Vline_number_display_limit)
28359 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28360 {
28361 w->base_line_pos = 0;
28362 w->base_line_number = 0;
28363 goto no_value;
28364 }
28365
28366 if (w->base_line_number > 0
28367 && w->base_line_pos > 0
28368 && w->base_line_pos <= startpos)
28369 {
28370 line = w->base_line_number;
28371 linepos = w->base_line_pos;
28372 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28373 }
28374 else
28375 {
28376 line = 1;
28377 linepos = BUF_BEGV (b);
28378 linepos_byte = BUF_BEGV_BYTE (b);
28379 }
28380
28381
28382 nlines = display_count_lines (linepos_byte,
28383 startpos_byte,
28384 startpos, &junk);
28385
28386 topline = nlines + line;
28387
28388
28389
28390
28391
28392 if (startpos == BUF_BEGV (b))
28393 {
28394 w->base_line_number = topline;
28395 w->base_line_pos = BUF_BEGV (b);
28396 }
28397 else if (nlines < height + 25 || nlines > height * 3 + 50
28398 || linepos == BUF_BEGV (b))
28399 {
28400 ptrdiff_t limit = BUF_BEGV (b);
28401 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28402 ptrdiff_t position;
28403 ptrdiff_t distance
28404 = (line_number_display_limit_width < 0 ? 0
28405 : ckd_mul (&distance, line_number_display_limit_width,
28406 height * 2 + 30)
28407 ? PTRDIFF_MAX : distance);
28408
28409 if (startpos - distance > limit)
28410 {
28411 limit = startpos - distance;
28412 limit_byte = CHAR_TO_BYTE (limit);
28413 }
28414
28415 nlines = display_count_lines (startpos_byte,
28416 limit_byte,
28417 - (height * 2 + 30),
28418 &position);
28419
28420
28421
28422 if (position == limit_byte && limit == startpos - distance)
28423 {
28424 w->base_line_pos = -1;
28425 w->base_line_number = 0;
28426 goto no_value;
28427 }
28428
28429 w->base_line_number = topline - nlines;
28430 w->base_line_pos = BYTE_TO_CHAR (position);
28431 }
28432
28433
28434 nlines = display_count_lines (startpos_byte,
28435 PT_BYTE, PT, &junk);
28436
28437
28438 line_number_displayed = true;
28439
28440
28441 pint2str (decode_mode_spec_buf, width, topline + nlines);
28442 return decode_mode_spec_buf;
28443 no_value:
28444 {
28445 char *p = decode_mode_spec_buf;
28446 int pad = width - 2;
28447 while (pad-- > 0)
28448 *p++ = ' ';
28449 *p++ = '?';
28450 *p++ = '?';
28451 *p = '\0';
28452 return decode_mode_spec_buf;
28453 }
28454 }
28455 break;
28456
28457 case 'm':
28458 obj = BVAR (b, mode_name);
28459 break;
28460
28461 case 'n':
28462 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28463 return " Narrow";
28464 break;
28465
28466
28467 case 'o':
28468 {
28469 ptrdiff_t toppos = marker_position (w->start);
28470 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28471 ptrdiff_t begv = BUF_BEGV (b);
28472 ptrdiff_t zv = BUF_ZV (b);
28473
28474 if (zv <= botpos)
28475 return toppos <= begv ? "All" : "Bottom";
28476 else if (toppos <= begv)
28477 return "Top";
28478 else
28479 {
28480 sprintf (decode_mode_spec_buf, "%2d%%",
28481 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28482 return decode_mode_spec_buf;
28483 }
28484 }
28485
28486
28487 case 'p':
28488 {
28489 ptrdiff_t pos = marker_position (w->start);
28490 ptrdiff_t begv = BUF_BEGV (b);
28491 ptrdiff_t zv = BUF_ZV (b);
28492
28493 if (w->window_end_pos <= BUF_Z (b) - zv)
28494 return pos <= begv ? "All" : "Bottom";
28495 else if (pos <= begv)
28496 return "Top";
28497 else
28498 {
28499 sprintf (decode_mode_spec_buf, "%2d%%",
28500 percent99 (pos - begv, zv - begv));
28501 return decode_mode_spec_buf;
28502 }
28503 }
28504
28505
28506 case 'P':
28507 {
28508 ptrdiff_t toppos = marker_position (w->start);
28509 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28510 ptrdiff_t begv = BUF_BEGV (b);
28511 ptrdiff_t zv = BUF_ZV (b);
28512
28513 if (zv <= botpos)
28514 return toppos <= begv ? "All" : "Bottom";
28515 else
28516 {
28517 sprintf (decode_mode_spec_buf,
28518 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28519 percent99 (botpos - begv, zv - begv));
28520 return decode_mode_spec_buf;
28521 }
28522 }
28523
28524
28525
28526 case 'q':
28527 {
28528 ptrdiff_t toppos = marker_position (w->start);
28529 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28530 ptrdiff_t begv = BUF_BEGV (b);
28531 ptrdiff_t zv = BUF_ZV (b);
28532 int top_perc, bot_perc;
28533
28534 if ((toppos <= begv) && (zv <= botpos))
28535 return "All ";
28536
28537 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28538 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28539
28540 if (top_perc == bot_perc)
28541 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28542 else
28543 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28544
28545 return decode_mode_spec_buf;
28546 }
28547
28548 case 's':
28549
28550 obj = Fget_buffer_process (Fcurrent_buffer ());
28551 if (NILP (obj))
28552 return "no process";
28553 #ifndef MSDOS
28554 obj = Fsymbol_name (Fprocess_status (obj));
28555 #endif
28556 break;
28557
28558 case '@':
28559 {
28560 specpdl_ref count = inhibit_garbage_collection ();
28561 Lisp_Object curdir = BVAR (current_buffer, directory);
28562 Lisp_Object val = Qnil;
28563
28564 if (STRINGP (curdir))
28565 val = safe_call1 (intern ("file-remote-p"), curdir);
28566
28567 val = unbind_to (count, val);
28568
28569 if (NILP (val))
28570 return "-";
28571 else
28572 return "@";
28573 }
28574
28575 case 'z':
28576
28577 case 'Z':
28578
28579 {
28580 bool eol_flag = (c == 'Z');
28581 char *p = decode_mode_spec_buf;
28582
28583 if (! FRAME_WINDOW_P (f))
28584 {
28585
28586
28587 p = decode_mode_spec_coding (CODING_ID_NAME
28588 (FRAME_KEYBOARD_CODING (f)->id),
28589 p, false);
28590 p = decode_mode_spec_coding (CODING_ID_NAME
28591 (FRAME_TERMINAL_CODING (f)->id),
28592 p, false);
28593 }
28594 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28595 p, eol_flag);
28596
28597 #if false
28598 #ifdef subprocesses
28599 obj = Fget_buffer_process (Fcurrent_buffer ());
28600 if (PROCESSP (obj))
28601 {
28602 p = decode_mode_spec_coding
28603 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28604 p = decode_mode_spec_coding
28605 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28606 }
28607 #endif
28608 #endif
28609 *p = 0;
28610 return decode_mode_spec_buf;
28611 }
28612 }
28613
28614 if (STRINGP (obj))
28615 {
28616 *string = obj;
28617 return SSDATA (obj);
28618 }
28619 else
28620 return "";
28621 }
28622
28623
28624
28625
28626 ptrdiff_t
28627 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28628 {
28629 ptrdiff_t ignored;
28630 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28631 }
28632
28633
28634
28635
28636
28637
28638
28639
28640
28641
28642
28643 static ptrdiff_t
28644 display_count_lines (ptrdiff_t start_byte,
28645 ptrdiff_t limit_byte, ptrdiff_t count,
28646 ptrdiff_t *byte_pos_ptr)
28647 {
28648 register unsigned char *cursor;
28649 unsigned char *base;
28650
28651 register ptrdiff_t ceiling;
28652 register unsigned char *ceiling_addr;
28653 ptrdiff_t orig_count = count;
28654
28655
28656
28657 bool selective_display
28658 = (!NILP (BVAR (current_buffer, selective_display))
28659 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28660
28661 if (count > 0)
28662 {
28663 while (start_byte < limit_byte)
28664 {
28665 ceiling = BUFFER_CEILING_OF (start_byte);
28666 ceiling = min (limit_byte - 1, ceiling);
28667 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28668 base = (cursor = BYTE_POS_ADDR (start_byte));
28669
28670 do
28671 {
28672 if (selective_display)
28673 {
28674 while (*cursor != '\n' && *cursor != 015
28675 && ++cursor != ceiling_addr)
28676 continue;
28677 if (cursor == ceiling_addr)
28678 break;
28679 }
28680 else
28681 {
28682 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28683 if (! cursor)
28684 break;
28685 }
28686
28687 cursor++;
28688
28689 if (--count == 0)
28690 {
28691 start_byte += cursor - base;
28692 *byte_pos_ptr = start_byte;
28693 return orig_count;
28694 }
28695 }
28696 while (cursor < ceiling_addr);
28697
28698 start_byte += ceiling_addr - base;
28699 }
28700 }
28701 else
28702 {
28703 while (start_byte > limit_byte)
28704 {
28705 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28706 ceiling = max (limit_byte, ceiling);
28707 ceiling_addr = BYTE_POS_ADDR (ceiling);
28708 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28709 while (true)
28710 {
28711 if (selective_display)
28712 {
28713 while (--cursor >= ceiling_addr
28714 && *cursor != '\n' && *cursor != 015)
28715 continue;
28716 if (cursor < ceiling_addr)
28717 break;
28718 }
28719 else
28720 {
28721 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28722 if (! cursor)
28723 break;
28724 }
28725
28726 if (++count == 0)
28727 {
28728 start_byte += cursor - base + 1;
28729 *byte_pos_ptr = start_byte;
28730
28731
28732 return - orig_count - 1;
28733 }
28734 }
28735 start_byte += ceiling_addr - base;
28736 }
28737 }
28738
28739 *byte_pos_ptr = limit_byte;
28740
28741 if (count < 0)
28742 return - orig_count + count;
28743 return orig_count - count;
28744
28745 }
28746
28747
28748
28749
28750
28751
28752
28753
28754
28755
28756
28757
28758
28759
28760
28761
28762
28763
28764
28765
28766
28767
28768
28769
28770
28771
28772
28773
28774
28775
28776
28777
28778
28779
28780
28781
28782
28783
28784
28785
28786
28787
28788
28789
28790
28791 static int
28792 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28793 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28794 int field_width, int precision, int max_x, int multibyte)
28795 {
28796 int hpos_at_start = it->hpos;
28797 int saved_face_id = it->face_id;
28798 struct glyph_row *row = it->glyph_row;
28799 ptrdiff_t it_charpos;
28800
28801
28802
28803 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28804 start, precision, field_width, multibyte);
28805
28806 if (string && STRINGP (lisp_string))
28807
28808
28809 it->stop_charpos = it->end_charpos;
28810
28811
28812
28813 if (STRINGP (face_string))
28814 {
28815 ptrdiff_t endptr;
28816 struct face *face;
28817
28818 it->face_id
28819 = face_at_string_position (it->w, face_string, face_string_pos,
28820 0, &endptr, it->base_face_id, false, 0);
28821 face = FACE_FROM_ID (it->f, it->face_id);
28822 it->face_box_p = face->box != FACE_NO_BOX;
28823
28824
28825
28826
28827 if (NILP (lisp_string))
28828 {
28829 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28830 face_string);
28831 if (!NILP (display))
28832 {
28833 Lisp_Object min_width = plist_get (display, Qmin_width);
28834 if (!NILP (min_width))
28835 display_min_width (it, 0, face_string, min_width);
28836 }
28837 }
28838 }
28839
28840
28841
28842 if (max_x <= 0)
28843 max_x = it->last_visible_x;
28844 else
28845 max_x = min (max_x, it->last_visible_x);
28846
28847
28848
28849 if (it->current_x < it->first_visible_x)
28850 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28851 MOVE_TO_POS | MOVE_TO_X);
28852
28853 row->ascent = it->max_ascent;
28854 row->height = it->max_ascent + it->max_descent;
28855 row->phys_ascent = it->max_phys_ascent;
28856 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28857 row->extra_line_spacing = it->max_extra_line_spacing;
28858
28859 if (STRINGP (it->string))
28860 it_charpos = IT_STRING_CHARPOS (*it);
28861 else
28862 it_charpos = IT_CHARPOS (*it);
28863
28864
28865
28866 while (it->current_x < max_x)
28867 {
28868 int x_before, x, n_glyphs_before, i, nglyphs;
28869
28870
28871 if (!get_next_display_element (it))
28872 break;
28873
28874
28875 x_before = it->current_x;
28876 n_glyphs_before = row->used[TEXT_AREA];
28877 PRODUCE_GLYPHS (it);
28878
28879 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28880 i = 0;
28881 x = x_before;
28882 while (i < nglyphs)
28883 {
28884 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28885
28886 if (it->line_wrap != TRUNCATE
28887 && x + glyph->pixel_width > max_x)
28888 {
28889
28890 if (CHAR_GLYPH_PADDING_P (*glyph))
28891 {
28892
28893 if (row->reversed_p)
28894 unproduce_glyphs (it, row->used[TEXT_AREA]
28895 - n_glyphs_before);
28896 row->used[TEXT_AREA] = n_glyphs_before;
28897 it->current_x = x_before;
28898 }
28899 else
28900 {
28901 if (row->reversed_p)
28902 unproduce_glyphs (it, row->used[TEXT_AREA]
28903 - (n_glyphs_before + i));
28904 row->used[TEXT_AREA] = n_glyphs_before + i;
28905 it->current_x = x;
28906 }
28907 break;
28908 }
28909 else if (x + glyph->pixel_width >= it->first_visible_x)
28910 {
28911
28912 ++it->hpos;
28913 if (x < it->first_visible_x)
28914 row->x = x - it->first_visible_x;
28915 }
28916 else
28917 {
28918
28919
28920 emacs_abort ();
28921 }
28922
28923 row->ascent = max (row->ascent, it->max_ascent);
28924 row->height = max (row->height, it->max_ascent + it->max_descent);
28925 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28926 row->phys_height = max (row->phys_height,
28927 it->max_phys_ascent + it->max_phys_descent);
28928 row->extra_line_spacing = max (row->extra_line_spacing,
28929 it->max_extra_line_spacing);
28930 x += glyph->pixel_width;
28931 ++i;
28932 }
28933
28934
28935 if (i < nglyphs)
28936 break;
28937
28938
28939 if (ITERATOR_AT_END_OF_LINE_P (it))
28940 {
28941 it->continuation_lines_width = 0;
28942 break;
28943 }
28944
28945 set_iterator_to_next (it, true);
28946 if (STRINGP (it->string))
28947 it_charpos = IT_STRING_CHARPOS (*it);
28948 else
28949 it_charpos = IT_CHARPOS (*it);
28950
28951
28952 if (it->line_wrap == TRUNCATE
28953 && it->current_x >= it->last_visible_x)
28954 {
28955
28956
28957
28958
28959
28960
28961 if (it_charpos <= it->string_nchars)
28962 {
28963 if (!FRAME_WINDOW_P (it->f))
28964 {
28965 int ii, n;
28966
28967 if (it->current_x > it->last_visible_x)
28968 {
28969
28970
28971 bool mode_line_p = false;
28972
28973
28974
28975 if (row->mode_line_p)
28976 {
28977 struct window *w = it->w;
28978 if (row == MATRIX_MODE_LINE_ROW (w->desired_matrix))
28979 mode_line_p = true;
28980 }
28981 if (!row->reversed_p)
28982 {
28983 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
28984 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28985 break;
28986 }
28987 else
28988 {
28989 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
28990 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28991 break;
28992 unproduce_glyphs (it, ii + 1);
28993 ii = row->used[TEXT_AREA] - (ii + 1);
28994 }
28995 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
28996 {
28997 row->used[TEXT_AREA] = ii;
28998 if (row->mode_line_p)
28999 pad_mode_line (it, mode_line_p);
29000 else
29001 produce_special_glyphs (it, IT_TRUNCATION);
29002 }
29003 }
29004 produce_special_glyphs (it, IT_TRUNCATION);
29005 }
29006 row->truncated_on_right_p = true;
29007 }
29008 break;
29009 }
29010 }
29011
29012
29013 if (it->first_visible_x
29014 && it_charpos > 0)
29015 {
29016 if (!FRAME_WINDOW_P (it->f)
29017 || (row->reversed_p
29018 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29019 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
29020 insert_left_trunc_glyphs (it);
29021 row->truncated_on_left_p = true;
29022 }
29023
29024 it->face_id = saved_face_id;
29025
29026
29027 return it->hpos - hpos_at_start;
29028 }
29029
29030
29031
29032
29033
29034
29035
29036
29037
29038
29039
29040 int
29041 invisible_prop (Lisp_Object propval, Lisp_Object list)
29042 {
29043 Lisp_Object tail, proptail;
29044
29045 for (tail = list; CONSP (tail); tail = XCDR (tail))
29046 {
29047 register Lisp_Object tem;
29048 tem = XCAR (tail);
29049 if (EQ (propval, tem))
29050 return 1;
29051 if (CONSP (tem) && EQ (propval, XCAR (tem)))
29052 return NILP (XCDR (tem)) ? 1 : 2;
29053 }
29054
29055 if (CONSP (propval))
29056 {
29057 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
29058 {
29059 Lisp_Object propelt;
29060 propelt = XCAR (proptail);
29061 for (tail = list; CONSP (tail); tail = XCDR (tail))
29062 {
29063 register Lisp_Object tem;
29064 tem = XCAR (tail);
29065 if (EQ (propelt, tem))
29066 return 1;
29067 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
29068 return NILP (XCDR (tem)) ? 1 : 2;
29069 }
29070 }
29071 }
29072
29073 return 0;
29074 }
29075
29076 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
29077 doc:
29078
29079
29080
29081
29082
29083
29084
29085
29086
29087
29088
29089 )
29090 (Lisp_Object pos)
29091 {
29092 Lisp_Object prop
29093 = (FIXNATP (pos) || MARKERP (pos)
29094 ? Fget_char_property (pos, Qinvisible, Qnil)
29095 : pos);
29096 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
29097 return (invis == 0 ? Qnil
29098 : invis == 1 ? Qt
29099 : make_fixnum (invis));
29100 }
29101
29102
29103
29104
29105
29106
29107
29108
29109
29110
29111
29112
29113
29114
29115
29116
29117
29118
29119
29120
29121
29122
29123
29124
29125
29126
29127
29128
29129
29130
29131
29132
29133
29134
29135
29136
29137
29138
29139
29140
29141
29142
29143
29144
29145
29146
29147
29148
29149
29150
29151
29152
29153
29154
29155
29156
29157
29158
29159
29160
29161
29162
29163
29164
29165
29166
29167
29168
29169
29170
29171
29172
29173
29174
29175
29176
29177
29178
29179
29180
29181
29182 static bool
29183 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
29184 struct font *font, bool width_p, int *align_to)
29185 {
29186
29187
29188
29189
29190 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
29191 double pixels;
29192
29193 # define OK_PIXELS(val) (*res = (val), true)
29194 # define OK_ALIGN_TO(val) (*align_to = (val), true)
29195
29196 if (NILP (prop))
29197 return OK_PIXELS (0);
29198
29199 eassert (FRAME_LIVE_P (it->f));
29200
29201 if (SYMBOLP (prop))
29202 {
29203 if (SCHARS (SYMBOL_NAME (prop)) == 2)
29204 {
29205 char *unit = SSDATA (SYMBOL_NAME (prop));
29206
29207
29208 if (unit[0] == 'i' && unit[1] == 'n')
29209 pixels = 1.0;
29210 else if (unit[0] == 'm' && unit[1] == 'm')
29211 pixels = 25.4;
29212 else if (unit[0] == 'c' && unit[1] == 'm')
29213 pixels = 2.54;
29214 else
29215 pixels = 0;
29216 if (pixels > 0)
29217 {
29218 double ppi = (width_p ? FRAME_RES_X (it->f)
29219 : FRAME_RES_Y (it->f));
29220
29221 if (ppi > 0)
29222 return OK_PIXELS (ppi / pixels);
29223 return false;
29224 }
29225 }
29226
29227 #ifdef HAVE_WINDOW_SYSTEM
29228
29229 if (EQ (prop, Qheight))
29230 return OK_PIXELS (font
29231 ? normal_char_height (font, -1)
29232 : FRAME_LINE_HEIGHT (it->f));
29233
29234 if (EQ (prop, Qwidth))
29235 return OK_PIXELS (font
29236 ? FONT_WIDTH (font)
29237 : FRAME_COLUMN_WIDTH (it->f));
29238 #else
29239 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29240 return OK_PIXELS (1);
29241 #endif
29242
29243
29244 if (EQ (prop, Qtext))
29245 return OK_PIXELS (width_p
29246 ? (window_box_width (it->w, TEXT_AREA)
29247 - lnum_pixel_width)
29248 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29249
29250
29251
29252
29253 if (align_to && *align_to < 0)
29254 {
29255 *res = 0;
29256
29257 if (EQ (prop, Qleft))
29258 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29259 + lnum_pixel_width);
29260
29261 if (EQ (prop, Qright))
29262 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29263
29264 if (EQ (prop, Qcenter))
29265 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29266 + lnum_pixel_width
29267 + window_box_width (it->w, TEXT_AREA) / 2);
29268
29269 if (EQ (prop, Qleft_fringe))
29270 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29271 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29272 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29273
29274 if (EQ (prop, Qright_fringe))
29275 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29276 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29277 : window_box_right_offset (it->w, TEXT_AREA));
29278
29279 if (EQ (prop, Qleft_margin))
29280 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29281
29282 if (EQ (prop, Qright_margin))
29283 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29284
29285 if (EQ (prop, Qscroll_bar))
29286 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29287 ? 0
29288 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29289 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29290 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29291 : 0)));
29292 }
29293 else
29294 {
29295
29296 if (EQ (prop, Qleft_fringe))
29297 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29298 if (EQ (prop, Qright_fringe))
29299 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29300 if (EQ (prop, Qleft_margin))
29301 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29302 if (EQ (prop, Qright_margin))
29303 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29304 if (EQ (prop, Qscroll_bar))
29305 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29306 }
29307
29308 prop = buffer_local_value (prop, it->w->contents);
29309 if (BASE_EQ (prop, Qunbound))
29310 prop = Qnil;
29311 }
29312
29313 if (NUMBERP (prop))
29314 {
29315 int base_unit = (width_p
29316 ? FRAME_COLUMN_WIDTH (it->f)
29317 : FRAME_LINE_HEIGHT (it->f));
29318 if (width_p && align_to && *align_to < 0)
29319 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29320 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29321 }
29322
29323 if (CONSP (prop))
29324 {
29325 Lisp_Object car = XCAR (prop);
29326 Lisp_Object cdr = XCDR (prop);
29327
29328 if (SYMBOLP (car))
29329 {
29330 #ifdef HAVE_WINDOW_SYSTEM
29331
29332 if (FRAME_WINDOW_P (it->f)
29333 && valid_image_p (prop))
29334 {
29335 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29336 struct image *img = IMAGE_FROM_ID (it->f, id);
29337
29338 return OK_PIXELS (width_p ? img->width : img->height);
29339 }
29340
29341 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29342 {
29343
29344 return OK_PIXELS (100);
29345 }
29346 #endif
29347
29348
29349 if (EQ (car, Qplus) || EQ (car, Qminus))
29350 {
29351 bool first = true;
29352 double px;
29353
29354 pixels = 0;
29355 while (CONSP (cdr))
29356 {
29357 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29358 font, width_p, align_to))
29359 return false;
29360 if (first)
29361 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29362 else
29363 pixels += px;
29364 cdr = XCDR (cdr);
29365 }
29366 if (EQ (car, Qminus))
29367 pixels = -pixels;
29368 return OK_PIXELS (pixels);
29369 }
29370
29371 car = buffer_local_value (car, it->w->contents);
29372 if (BASE_EQ (car, Qunbound))
29373 car = Qnil;
29374 }
29375
29376
29377 if (NUMBERP (car))
29378 {
29379 double fact;
29380 int offset =
29381 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29382 pixels = XFLOATINT (car);
29383 if (NILP (cdr))
29384 return OK_PIXELS (pixels + offset);
29385 if (calc_pixel_width_or_height (&fact, it, cdr,
29386 font, width_p, align_to))
29387 return OK_PIXELS (pixels * fact + offset);
29388 return false;
29389 }
29390
29391 return false;
29392 }
29393
29394 return false;
29395 }
29396
29397 void
29398 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29399 {
29400 #ifdef HAVE_WINDOW_SYSTEM
29401 normal_char_ascent_descent (font, -1, ascent, descent);
29402 #else
29403 *ascent = 1;
29404 *descent = 0;
29405 #endif
29406 }
29407
29408
29409
29410
29411
29412
29413 #ifdef HAVE_WINDOW_SYSTEM
29414
29415 #ifdef GLYPH_DEBUG
29416
29417 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29418 void
29419 dump_glyph_string (struct glyph_string *s)
29420 {
29421 fputs ("glyph string\n", stderr);
29422 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29423 s->x, s->y, s->width, s->height);
29424 fprintf (stderr, " ybase = %d\n", s->ybase);
29425 fprintf (stderr, " hl = %u\n", s->hl);
29426 fprintf (stderr, " left overhang = %d, right = %d\n",
29427 s->left_overhang, s->right_overhang);
29428 fprintf (stderr, " nchars = %d\n", s->nchars);
29429 fprintf (stderr, " extends to end of line = %d\n",
29430 s->extends_to_end_of_line_p);
29431 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29432 fprintf (stderr, " bg width = %d\n", s->background_width);
29433 }
29434
29435 #endif
29436
29437
29438
29439
29440
29441
29442
29443
29444
29445 #ifdef HAVE_NTGUI
29446
29447
29448
29449
29450
29451 # define ALLOCATE_HDC(hdc, f) \
29452 Lisp_Object prev_quit = Vinhibit_quit; \
29453 Vinhibit_quit = Qt; \
29454 HDC hdc = get_frame_dc ((f))
29455 # define RELEASE_HDC(hdc, f) \
29456 release_frame_dc ((f), (hdc)); \
29457 Vinhibit_quit = prev_quit
29458 #else
29459 # define ALLOCATE_HDC(hdc, f)
29460 # define RELEASE_HDC(hdc, f)
29461 #endif
29462
29463 static void
29464 init_glyph_string (struct glyph_string *s,
29465 #ifdef HAVE_NTGUI
29466 HDC hdc,
29467 #endif
29468 unsigned *char2b, struct window *w, struct glyph_row *row,
29469 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29470 {
29471 memset (s, 0, sizeof *s);
29472 s->w = w;
29473 s->f = XFRAME (w->frame);
29474 #ifdef HAVE_NTGUI
29475 s->hdc = hdc;
29476 #endif
29477 s->char2b = char2b;
29478 s->hl = hl;
29479 s->row = row;
29480 s->area = area;
29481 s->first_glyph = row->glyphs[area] + start;
29482 s->height = row->height;
29483 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29484 s->ybase = s->y + row->ascent;
29485 }
29486
29487
29488
29489
29490
29491 static void
29492 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29493 struct glyph_string *h, struct glyph_string *t)
29494 {
29495 if (h)
29496 {
29497 if (*head)
29498 (*tail)->next = h;
29499 else
29500 *head = h;
29501 h->prev = *tail;
29502 *tail = t;
29503 }
29504 }
29505
29506
29507
29508
29509
29510
29511 static void
29512 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29513 struct glyph_string *h, struct glyph_string *t)
29514 {
29515 if (h)
29516 {
29517 if (*head)
29518 (*head)->prev = t;
29519 else
29520 *tail = t;
29521 t->next = *head;
29522 *head = h;
29523 }
29524 }
29525
29526
29527
29528
29529
29530 static void
29531 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29532 struct glyph_string *s)
29533 {
29534 s->next = s->prev = NULL;
29535 append_glyph_string_lists (head, tail, s, s);
29536 }
29537
29538
29539
29540
29541
29542
29543
29544
29545 static struct face *
29546 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29547 unsigned *char2b, bool display_p)
29548 {
29549 struct face *face = FACE_FROM_ID (f, face_id);
29550 unsigned code = 0;
29551
29552 if (face->font)
29553 {
29554 code = face->font->driver->encode_char (face->font, c);
29555
29556 if (code == FONT_INVALID_CODE)
29557 code = 0;
29558 }
29559
29560 *char2b = code & 0xFFFF;
29561
29562
29563 #ifdef HAVE_X_WINDOWS
29564 if (display_p)
29565 #endif
29566 {
29567 eassert (face != NULL);
29568 prepare_face_for_display (f, face);
29569 }
29570
29571 return face;
29572 }
29573
29574
29575
29576
29577
29578
29579 static struct face *
29580 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29581 unsigned *char2b)
29582 {
29583 struct face *face;
29584 unsigned code = 0;
29585
29586 eassert (glyph->type == CHAR_GLYPH);
29587 face = FACE_FROM_ID (f, glyph->face_id);
29588
29589
29590 prepare_face_for_display (f, face);
29591
29592 if (face->font)
29593 {
29594 if (CHAR_BYTE8_P (glyph->u.ch))
29595 code = CHAR_TO_BYTE8 (glyph->u.ch);
29596 else
29597 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29598
29599 if (code == FONT_INVALID_CODE)
29600 code = 0;
29601 }
29602
29603
29604 *char2b = code & 0xFFFF;
29605 return face;
29606 }
29607
29608
29609
29610
29611
29612 static bool
29613 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29614 {
29615 unsigned code;
29616
29617 if (CHAR_BYTE8_P (c))
29618 code = CHAR_TO_BYTE8 (c);
29619 else
29620 code = font->driver->encode_char (font, c);
29621
29622 if (code == FONT_INVALID_CODE)
29623 return false;
29624
29625
29626 *char2b = code & 0xFFFF;
29627 return true;
29628 }
29629
29630
29631
29632
29633
29634
29635
29636
29637
29638
29639
29640
29641 static int
29642 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29643 int overlaps)
29644 {
29645 int i;
29646
29647
29648
29649 struct face *face;
29650
29651 eassert (s);
29652
29653 s->for_overlaps = overlaps;
29654 s->face = NULL;
29655 s->font = NULL;
29656 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29657 {
29658 int c = COMPOSITION_GLYPH (s->cmp, i);
29659
29660
29661
29662 if (c != '\t')
29663 {
29664 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29665 -1, Qnil);
29666
29667 face = get_char_face_and_encoding (s->f, c, face_id,
29668 s->char2b + i, true);
29669 if (face)
29670 {
29671 if (! s->face)
29672 {
29673 s->face = face;
29674 s->font = s->face->font;
29675 }
29676 else if (s->face != face)
29677 break;
29678 }
29679 }
29680 ++s->nchars;
29681 }
29682 s->cmp_to = i;
29683
29684 if (s->face == NULL)
29685 {
29686 s->face = base_face->ascii_face;
29687 s->font = s->face->font;
29688 }
29689
29690 if (s->hl == DRAW_MOUSE_FACE
29691 || (s->hl == DRAW_CURSOR
29692 && MATRIX_ROW (s->w->current_matrix,
29693 s->w->phys_cursor.vpos)->mouse_face_p
29694 && cursor_in_mouse_face_p (s->w)))
29695 {
29696 int c = COMPOSITION_GLYPH (s->cmp, 0);
29697 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29698 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29699 if (!s->face)
29700 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29701
29702 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29703 prepare_face_for_display (s->f, s->face);
29704 }
29705
29706
29707
29708 s->width = s->first_glyph->pixel_width;
29709
29710
29711
29712
29713
29714 if (s->font == NULL)
29715 {
29716 s->font_not_found_p = true;
29717 s->font = FRAME_FONT (s->f);
29718 }
29719
29720
29721 s->ybase += s->first_glyph->voffset;
29722
29723 return s->cmp_to;
29724 }
29725
29726 static int
29727 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29728 int start, int end, int overlaps)
29729 {
29730 struct glyph *glyph, *last;
29731 int voffset;
29732 Lisp_Object lgstring;
29733 int i;
29734 bool glyph_not_available_p;
29735
29736 s->for_overlaps = overlaps;
29737 glyph = s->row->glyphs[s->area] + start;
29738 last = s->row->glyphs[s->area] + end;
29739 voffset = glyph->voffset;
29740 glyph_not_available_p = glyph->glyph_not_available_p;
29741 s->cmp_id = glyph->u.cmp.id;
29742 s->cmp_from = glyph->slice.cmp.from;
29743 s->cmp_to = glyph->slice.cmp.to + 1;
29744 if (s->hl == DRAW_MOUSE_FACE
29745 || (s->hl == DRAW_CURSOR
29746 && MATRIX_ROW (s->w->current_matrix,
29747 s->w->phys_cursor.vpos)->mouse_face_p
29748 && cursor_in_mouse_face_p (s->w)))
29749 {
29750 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29751 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29752 if (!s->face)
29753 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29754 prepare_face_for_display (s->f, s->face);
29755 }
29756 else
29757 s->face = FACE_FROM_ID (s->f, face_id);
29758 lgstring = composition_gstring_from_id (s->cmp_id);
29759 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29760
29761
29762 s->width = s->first_glyph->pixel_width;
29763 glyph++;
29764 while (glyph < last
29765 && glyph->u.cmp.automatic
29766 && glyph->u.cmp.id == s->cmp_id
29767 && glyph->face_id == face_id
29768 && s->cmp_to == glyph->slice.cmp.from
29769 && glyph->glyph_not_available_p == glyph_not_available_p)
29770 {
29771 s->width += glyph->pixel_width;
29772 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29773 }
29774
29775 for (i = s->cmp_from; i < s->cmp_to; i++)
29776 {
29777 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29778 unsigned code = LGLYPH_CODE (lglyph);
29779
29780
29781 s->char2b[i] = code & 0xFFFF;
29782 }
29783
29784
29785
29786
29787 if (glyph_not_available_p)
29788 s->font_not_found_p = true;
29789
29790
29791 s->ybase += voffset;
29792
29793 return glyph - s->row->glyphs[s->area];
29794 }
29795
29796
29797
29798
29799
29800
29801
29802 static int
29803 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29804 int start, int end, int overlaps)
29805 {
29806 struct glyph *glyph, *last;
29807 int voffset;
29808
29809 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29810 s->for_overlaps = overlaps;
29811 glyph = s->row->glyphs[s->area] + start;
29812 last = s->row->glyphs[s->area] + end;
29813 voffset = glyph->voffset;
29814 s->face = FACE_FROM_ID (s->f, face_id);
29815 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29816 if (s->hl == DRAW_MOUSE_FACE
29817 || (s->hl == DRAW_CURSOR
29818 && MATRIX_ROW (s->w->current_matrix,
29819 s->w->phys_cursor.vpos)->mouse_face_p
29820 && cursor_in_mouse_face_p (s->w)))
29821 {
29822 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29823 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29824 if (!s->face)
29825 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29826 prepare_face_for_display (s->f, s->face);
29827 }
29828 s->nchars = 1;
29829 s->width = glyph->pixel_width;
29830 glyph++;
29831 while (glyph < last
29832 && glyph->type == GLYPHLESS_GLYPH
29833 && glyph->voffset == voffset
29834 && glyph->face_id == face_id)
29835 {
29836 s->nchars++;
29837 s->width += glyph->pixel_width;
29838 glyph++;
29839 }
29840 s->ybase += voffset;
29841 return glyph - s->row->glyphs[s->area];
29842 }
29843
29844
29845
29846
29847
29848
29849
29850
29851
29852
29853
29854 static int
29855 fill_glyph_string (struct glyph_string *s, int face_id,
29856 int start, int end, int overlaps)
29857 {
29858 struct glyph *glyph, *last;
29859 int voffset;
29860 bool glyph_not_available_p;
29861
29862 eassert (s->f == XFRAME (s->w->frame));
29863 eassert (s->nchars == 0);
29864 eassert (start >= 0 && end > start);
29865
29866 s->for_overlaps = overlaps;
29867 glyph = s->row->glyphs[s->area] + start;
29868 last = s->row->glyphs[s->area] + end;
29869 voffset = glyph->voffset;
29870 s->padding_p = glyph->padding_p;
29871 glyph_not_available_p = glyph->glyph_not_available_p;
29872
29873 while (glyph < last
29874 && glyph->type == CHAR_GLYPH
29875 && glyph->voffset == voffset
29876
29877 && glyph->face_id == face_id
29878 && glyph->glyph_not_available_p == glyph_not_available_p)
29879 {
29880 s->face = get_glyph_face_and_encoding (s->f, glyph,
29881 s->char2b + s->nchars);
29882 ++s->nchars;
29883 eassert (s->nchars <= end - start);
29884 s->width += glyph->pixel_width;
29885 if (glyph++->padding_p != s->padding_p)
29886 break;
29887 }
29888
29889 s->font = s->face->font;
29890
29891 if (s->hl == DRAW_MOUSE_FACE
29892 || (s->hl == DRAW_CURSOR
29893 && MATRIX_ROW (s->w->current_matrix,
29894 s->w->phys_cursor.vpos)->mouse_face_p
29895 && cursor_in_mouse_face_p (s->w)))
29896 {
29897 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29898 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29899 if (!s->face)
29900 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29901 s->face
29902 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29903 s->first_glyph->u.ch, -1, Qnil));
29904 prepare_face_for_display (s->f, s->face);
29905 }
29906
29907
29908
29909
29910
29911 if (s->font == NULL || glyph_not_available_p)
29912 {
29913 s->font_not_found_p = true;
29914 s->font = FRAME_FONT (s->f);
29915 }
29916
29917
29918 s->ybase += voffset;
29919
29920 eassert (s->face && s->face->gc);
29921 return glyph - s->row->glyphs[s->area];
29922 }
29923
29924
29925
29926
29927 static void
29928 fill_image_glyph_string (struct glyph_string *s)
29929 {
29930 eassert (s->first_glyph->type == IMAGE_GLYPH);
29931 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29932 eassert (s->img);
29933 s->slice = s->first_glyph->slice.img;
29934 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29935 s->font = s->face->font;
29936 if (s->hl == DRAW_MOUSE_FACE
29937 || (s->hl == DRAW_CURSOR
29938 && MATRIX_ROW (s->w->current_matrix,
29939 s->w->phys_cursor.vpos)->mouse_face_p
29940 && cursor_in_mouse_face_p (s->w)))
29941 {
29942 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29943 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29944 if (!s->face)
29945 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29946 prepare_face_for_display (s->f, s->face);
29947 }
29948 s->width = s->first_glyph->pixel_width;
29949
29950
29951 s->ybase += s->first_glyph->voffset;
29952 }
29953
29954
29955 #ifdef HAVE_XWIDGETS
29956 static void
29957 fill_xwidget_glyph_string (struct glyph_string *s)
29958 {
29959 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29960 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29961 s->font = s->face->font;
29962 if (s->hl == DRAW_MOUSE_FACE
29963 || (s->hl == DRAW_CURSOR
29964 && MATRIX_ROW (s->w->current_matrix,
29965 s->w->phys_cursor.vpos)->mouse_face_p
29966 && cursor_in_mouse_face_p (s->w)))
29967 {
29968 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29969 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29970 if (!s->face)
29971 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29972 prepare_face_for_display (s->f, s->face);
29973 }
29974 s->width = s->first_glyph->pixel_width;
29975 s->ybase += s->first_glyph->voffset;
29976 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
29977 }
29978 #endif
29979
29980
29981
29982
29983
29984
29985
29986 static int
29987 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
29988 {
29989 struct glyph *glyph, *last;
29990 int voffset, face_id;
29991
29992 eassert (s->first_glyph->type == STRETCH_GLYPH);
29993
29994 glyph = s->row->glyphs[s->area] + start;
29995 last = s->row->glyphs[s->area] + end;
29996 face_id = glyph->face_id;
29997 s->face = FACE_FROM_ID (s->f, face_id);
29998 s->font = s->face->font;
29999 if (s->hl == DRAW_MOUSE_FACE
30000 || (s->hl == DRAW_CURSOR
30001 && MATRIX_ROW (s->w->current_matrix,
30002 s->w->phys_cursor.vpos)->mouse_face_p
30003 && cursor_in_mouse_face_p (s->w)))
30004 {
30005 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
30006 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
30007 if (!s->face)
30008 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30009 prepare_face_for_display (s->f, s->face);
30010 }
30011 s->width = glyph->pixel_width;
30012 s->nchars = 1;
30013 voffset = glyph->voffset;
30014
30015 for (++glyph;
30016 (glyph < last
30017 && glyph->type == STRETCH_GLYPH
30018 && glyph->voffset == voffset
30019 && glyph->face_id == face_id);
30020 ++glyph)
30021 s->width += glyph->pixel_width;
30022
30023
30024 s->ybase += voffset;
30025
30026
30027
30028 eassert (s->face);
30029 return glyph - s->row->glyphs[s->area];
30030 }
30031
30032 static struct font_metrics *
30033 get_per_char_metric (struct font *font, const unsigned *char2b)
30034 {
30035 static struct font_metrics metrics;
30036
30037 if (! font)
30038 return NULL;
30039 if (*char2b == FONT_INVALID_CODE)
30040 return NULL;
30041
30042 font->driver->text_extents (font, char2b, 1, &metrics);
30043 return &metrics;
30044 }
30045
30046
30047
30048
30049
30050
30051
30052 static void
30053 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
30054 {
30055 *ascent = FONT_BASE (font);
30056 *descent = FONT_DESCENT (font);
30057
30058 if (FONT_TOO_HIGH (font))
30059 {
30060 unsigned char2b;
30061
30062
30063
30064 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
30065 {
30066 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
30067 eassume (pcm);
30068
30069 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
30070 {
30071
30072
30073
30074 *ascent = pcm->ascent + 1;
30075 *descent = pcm->descent + 1;
30076 }
30077 }
30078 }
30079 }
30080
30081
30082
30083
30084
30085
30086 static int
30087 normal_char_height (struct font *font, int c)
30088 {
30089 int ascent, descent;
30090
30091 normal_char_ascent_descent (font, c, &ascent, &descent);
30092
30093 return ascent + descent;
30094 }
30095
30096
30097
30098
30099
30100
30101 void
30102 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
30103 {
30104 *left = *right = 0;
30105
30106 if (glyph->type == CHAR_GLYPH)
30107 {
30108 unsigned char2b;
30109 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
30110 if (face->font)
30111 {
30112 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
30113 if (pcm)
30114 {
30115 if (pcm->rbearing > pcm->width)
30116 *right = pcm->rbearing - pcm->width;
30117 if (pcm->lbearing < 0)
30118 *left = -pcm->lbearing;
30119 }
30120 }
30121 }
30122 else if (glyph->type == COMPOSITE_GLYPH)
30123 {
30124 if (! glyph->u.cmp.automatic)
30125 {
30126 struct composition *cmp = composition_table[glyph->u.cmp.id];
30127
30128 if (cmp->rbearing > cmp->pixel_width)
30129 *right = cmp->rbearing - cmp->pixel_width;
30130 if (cmp->lbearing < 0)
30131 *left = - cmp->lbearing;
30132 }
30133 else
30134 {
30135 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
30136 struct font_metrics metrics;
30137
30138 composition_gstring_width (gstring, glyph->slice.cmp.from,
30139 glyph->slice.cmp.to + 1, &metrics);
30140 if (metrics.rbearing > metrics.width)
30141 *right = metrics.rbearing - metrics.width;
30142 if (metrics.lbearing < 0)
30143 *left = - metrics.lbearing;
30144 }
30145 }
30146 }
30147
30148
30149
30150
30151
30152
30153 static int
30154 left_overwritten (struct glyph_string *s)
30155 {
30156 int k;
30157
30158 if (s->left_overhang)
30159 {
30160 int x = 0, i;
30161 struct glyph *glyphs = s->row->glyphs[s->area];
30162 int first = s->first_glyph - glyphs;
30163
30164 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
30165 x -= glyphs[i].pixel_width;
30166
30167 k = i + 1;
30168 }
30169 else
30170 k = -1;
30171
30172 return k;
30173 }
30174
30175
30176
30177
30178
30179
30180 static int
30181 left_overwriting (struct glyph_string *s)
30182 {
30183 int i, k, x;
30184 struct glyph *glyphs = s->row->glyphs[s->area];
30185 int first = s->first_glyph - glyphs;
30186
30187 k = -1;
30188 x = 0;
30189 for (i = first - 1; i >= 0; --i)
30190 {
30191 int left, right;
30192 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30193 if (x + right > 0)
30194 k = i;
30195 x -= glyphs[i].pixel_width;
30196 }
30197
30198 return k;
30199 }
30200
30201
30202
30203
30204
30205
30206 static int
30207 right_overwritten (struct glyph_string *s)
30208 {
30209 int k = -1;
30210
30211 if (s->right_overhang)
30212 {
30213 int x = 0, i;
30214 struct glyph *glyphs = s->row->glyphs[s->area];
30215 int first = (s->first_glyph - glyphs
30216 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30217 int end = s->row->used[s->area];
30218
30219 for (i = first; i < end && s->right_overhang > x; ++i)
30220 x += glyphs[i].pixel_width;
30221
30222 k = i;
30223 }
30224
30225 return k;
30226 }
30227
30228
30229
30230
30231
30232
30233 static int
30234 right_overwriting (struct glyph_string *s)
30235 {
30236 int i, k, x;
30237 int end = s->row->used[s->area];
30238 struct glyph *glyphs = s->row->glyphs[s->area];
30239 int first = (s->first_glyph - glyphs
30240 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30241
30242 k = -1;
30243 x = 0;
30244 for (i = first; i < end; ++i)
30245 {
30246 int left, right;
30247 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30248 if (x - left < 0)
30249 k = i;
30250 x += glyphs[i].pixel_width;
30251 }
30252
30253 return k;
30254 }
30255
30256
30257
30258
30259
30260
30261
30262
30263
30264
30265
30266 static void
30267 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30268 {
30269
30270
30271
30272 if (start == s->row->used[s->area]
30273 && ((s->row->fill_line_p
30274 && (s->hl == DRAW_NORMAL_TEXT
30275 || s->hl == DRAW_IMAGE_RAISED
30276 || s->hl == DRAW_IMAGE_SUNKEN))
30277 || s->hl == DRAW_MOUSE_FACE))
30278 s->extends_to_end_of_line_p = true;
30279
30280
30281
30282
30283 if (s->extends_to_end_of_line_p)
30284 s->background_width = last_x - s->x + 1;
30285 else
30286 {
30287 s->background_width = s->width;
30288 #ifdef HAVE_WINDOW_SYSTEM
30289 if (FRAME_WINDOW_P (s->f)
30290 && s->hl == DRAW_CURSOR
30291 && MATRIX_ROW (s->w->current_matrix,
30292 s->w->phys_cursor.vpos)->mouse_face_p
30293 && cursor_in_mouse_face_p (s->w))
30294 {
30295
30296
30297
30298
30299 struct glyph *g = s->first_glyph;
30300 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30301 s->background_width +=
30302 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30303 regular_face, s->face);
30304
30305 s->width = s->background_width;
30306 }
30307 #endif
30308 }
30309 }
30310
30311
30312
30313
30314
30315 static struct glyph_string *
30316 glyph_string_containing_background_width (struct glyph_string *s)
30317 {
30318 if (s->cmp)
30319 while (s->cmp_from)
30320 s = s->prev;
30321
30322 return s;
30323 }
30324
30325
30326
30327
30328
30329
30330 static void
30331 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30332 {
30333 if (backward_p)
30334 {
30335 while (s)
30336 {
30337 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30338 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30339 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30340 x -= s->width;
30341 s->x = x;
30342 s = s->prev;
30343 }
30344 }
30345 else
30346 {
30347 while (s)
30348 {
30349 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30350 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30351 s->x = x;
30352 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30353 x += s->width;
30354 s = s->next;
30355 }
30356 }
30357 }
30358
30359
30360
30361
30362
30363
30364
30365
30366
30367 #ifdef HAVE_NTGUI
30368
30369
30370 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30371 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30372 #else
30373 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30374 init_glyph_string (s, char2b, w, row, area, start, hl)
30375 #endif
30376
30377
30378
30379
30380
30381
30382
30383
30384
30385
30386
30387 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30388 do \
30389 { \
30390 s = alloca (sizeof *s); \
30391 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30392 START = fill_stretch_glyph_string (s, START, END); \
30393 append_glyph_string (&HEAD, &TAIL, s); \
30394 s->x = (X); \
30395 } \
30396 while (false)
30397
30398
30399
30400
30401
30402
30403
30404
30405
30406
30407 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30408 do \
30409 { \
30410 s = alloca (sizeof *s); \
30411 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30412 fill_image_glyph_string (s); \
30413 append_glyph_string (&HEAD, &TAIL, s); \
30414 ++START; \
30415 s->x = (X); \
30416 } \
30417 while (false)
30418
30419 #ifndef HAVE_XWIDGETS
30420 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30421 eassume (false)
30422 #else
30423 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30424 do \
30425 { \
30426 s = alloca (sizeof *s); \
30427 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30428 fill_xwidget_glyph_string (s); \
30429 append_glyph_string (&(HEAD), &(TAIL), s); \
30430 ++(START); \
30431 s->x = (X); \
30432 } \
30433 while (false)
30434 #endif
30435
30436
30437
30438
30439
30440
30441
30442
30443
30444
30445 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30446 do \
30447 { \
30448 int face_id; \
30449 unsigned *char2b; \
30450 \
30451 face_id = (row)->glyphs[area][START].face_id; \
30452 \
30453 s = alloca (sizeof *s); \
30454 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30455 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30456 append_glyph_string (&HEAD, &TAIL, s); \
30457 s->x = (X); \
30458 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30459 } \
30460 while (false)
30461
30462
30463
30464
30465
30466
30467
30468
30469
30470
30471
30472 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30473 do { \
30474 int face_id = (row)->glyphs[area][START].face_id; \
30475 struct face *base_face = FACE_FROM_ID (f, face_id); \
30476 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30477 struct composition *cmp = composition_table[cmp_id]; \
30478 unsigned *char2b; \
30479 struct glyph_string *first_s = NULL; \
30480 int n; \
30481 \
30482 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30483 \
30484
30485 \
30486 for (n = 0; n < cmp->glyph_len;) \
30487 { \
30488 s = alloca (sizeof *s); \
30489 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30490 append_glyph_string (&(HEAD), &(TAIL), s); \
30491 s->cmp = cmp; \
30492 s->cmp_from = n; \
30493 s->x = (X); \
30494 if (n == 0) \
30495 first_s = s; \
30496 n = fill_composite_glyph_string (s, base_face, overlaps); \
30497 } \
30498 \
30499 ++START; \
30500 s = first_s; \
30501 } while (false)
30502
30503
30504
30505
30506
30507 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30508 do { \
30509 int face_id; \
30510 unsigned *char2b; \
30511 Lisp_Object gstring; \
30512 \
30513 face_id = (row)->glyphs[area][START].face_id; \
30514 gstring = (composition_gstring_from_id \
30515 ((row)->glyphs[area][START].u.cmp.id)); \
30516 s = alloca (sizeof *s); \
30517 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30518 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30519 append_glyph_string (&(HEAD), &(TAIL), s); \
30520 s->x = (X); \
30521 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30522 } while (false)
30523
30524
30525
30526
30527
30528
30529 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30530 do \
30531 { \
30532 int face_id; \
30533 \
30534 face_id = (row)->glyphs[area][START].face_id; \
30535 \
30536 s = alloca (sizeof *s); \
30537 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30538 append_glyph_string (&HEAD, &TAIL, s); \
30539 s->x = (X); \
30540 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30541 overlaps); \
30542 } \
30543 while (false)
30544
30545
30546
30547
30548
30549
30550
30551
30552
30553
30554
30555
30556 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30557 do \
30558 { \
30559 HEAD = TAIL = NULL; \
30560 while (START < END) \
30561 { \
30562 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30563 switch (first_glyph->type) \
30564 { \
30565 case CHAR_GLYPH: \
30566 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30567 HL, X, LAST_X); \
30568 break; \
30569 \
30570 case COMPOSITE_GLYPH: \
30571 if (first_glyph->u.cmp.automatic) \
30572 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30573 HL, X, LAST_X); \
30574 else \
30575 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30576 HL, X, LAST_X); \
30577 break; \
30578 \
30579 case STRETCH_GLYPH: \
30580 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30581 HL, X, LAST_X); \
30582 break; \
30583 \
30584 case IMAGE_GLYPH: \
30585 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30586 HL, X, LAST_X); \
30587 break;
30588
30589 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30590 case XWIDGET_GLYPH: \
30591 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30592 HL, X, LAST_X); \
30593 break;
30594
30595 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30596 case GLYPHLESS_GLYPH: \
30597 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30598 HL, X, LAST_X); \
30599 break; \
30600 \
30601 default: \
30602 emacs_abort (); \
30603 } \
30604 \
30605 if (s) \
30606 { \
30607 set_glyph_string_background_width (s, START, LAST_X); \
30608 (X) += s->width; \
30609 } \
30610 } \
30611 } while (false)
30612
30613
30614 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30615 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30616 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30617 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30618
30619
30620
30621
30622
30623
30624
30625
30626
30627
30628
30629
30630
30631
30632
30633
30634
30635
30636
30637
30638
30639
30640
30641
30642 static int
30643 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30644 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30645 enum draw_glyphs_face hl, int overlaps)
30646 {
30647 struct glyph_string *head, *tail;
30648 struct glyph_string *s;
30649 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30650 int i, j, x_reached, last_x, area_left = 0;
30651 struct frame *f = XFRAME (WINDOW_FRAME (w));
30652
30653 ALLOCATE_HDC (hdc, f);
30654
30655
30656 end = min (end, row->used[area]);
30657 start = clip_to_bounds (0, start, end);
30658
30659
30660
30661 if (row->full_width_p)
30662 {
30663
30664
30665 area_left = WINDOW_LEFT_EDGE_X (w);
30666 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30667 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30668 }
30669 else
30670 {
30671 area_left = window_box_left (w, area);
30672 last_x = area_left + window_box_width (w, area);
30673 }
30674 x += area_left;
30675
30676
30677
30678
30679
30680 i = start;
30681 USE_SAFE_ALLOCA;
30682 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30683 if (tail)
30684 {
30685 s = glyph_string_containing_background_width (tail);
30686 x_reached = s->x + s->background_width;
30687 }
30688 else
30689 x_reached = x;
30690
30691
30692
30693
30694 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30695 {
30696 struct glyph_string *h, *t;
30697 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30698 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30699 bool check_mouse_face = false;
30700 int dummy_x = 0;
30701
30702
30703
30704 if (area == TEXT_AREA && row->mouse_face_p
30705 && hlinfo->mouse_face_beg_row >= 0
30706 && hlinfo->mouse_face_end_row >= 0)
30707 {
30708 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30709
30710 if (row_vpos >= hlinfo->mouse_face_beg_row
30711 && row_vpos <= hlinfo->mouse_face_end_row)
30712 {
30713 check_mouse_face = true;
30714 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30715 ? hlinfo->mouse_face_beg_col : 0;
30716 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30717 ? hlinfo->mouse_face_end_col
30718 : row->used[TEXT_AREA];
30719 }
30720 }
30721
30722
30723 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30724 for (s = head; s; s = s->next)
30725 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30726
30727
30728
30729
30730
30731
30732 i = left_overwritten (head);
30733 if (i >= 0)
30734 {
30735 enum draw_glyphs_face overlap_hl;
30736
30737
30738
30739
30740
30741
30742
30743
30744 if (check_mouse_face
30745 && mouse_beg_col < start && mouse_end_col > i)
30746 overlap_hl = DRAW_MOUSE_FACE;
30747 else
30748 overlap_hl = DRAW_NORMAL_TEXT;
30749
30750 if (hl != overlap_hl)
30751 clip_head = head;
30752 j = i;
30753 BUILD_GLYPH_STRINGS (j, start, h, t,
30754 overlap_hl, dummy_x, last_x);
30755 start = i;
30756 compute_overhangs_and_x (t, head->x, true);
30757 prepend_glyph_string_lists (&head, &tail, h, t);
30758 if (clip_head == NULL)
30759 clip_head = head;
30760 }
30761
30762
30763
30764
30765
30766
30767
30768
30769 i = left_overwriting (head);
30770 if (i >= 0)
30771 {
30772 enum draw_glyphs_face overlap_hl;
30773
30774 if (check_mouse_face
30775 && mouse_beg_col < start && mouse_end_col > i)
30776 overlap_hl = DRAW_MOUSE_FACE;
30777 else
30778 overlap_hl = DRAW_NORMAL_TEXT;
30779
30780 if (hl == overlap_hl || clip_head == NULL)
30781 clip_head = head;
30782 BUILD_GLYPH_STRINGS (i, start, h, t,
30783 overlap_hl, dummy_x, last_x);
30784 for (s = h; s; s = s->next)
30785 s->background_filled_p = true;
30786 compute_overhangs_and_x (t, head->x, true);
30787 prepend_glyph_string_lists (&head, &tail, h, t);
30788 }
30789
30790
30791
30792
30793
30794 i = right_overwritten (tail);
30795 if (i >= 0)
30796 {
30797 enum draw_glyphs_face overlap_hl;
30798
30799 if (check_mouse_face
30800 && mouse_beg_col < i && mouse_end_col > end)
30801 overlap_hl = DRAW_MOUSE_FACE;
30802 else
30803 overlap_hl = DRAW_NORMAL_TEXT;
30804
30805 if (hl != overlap_hl)
30806 clip_tail = tail;
30807 BUILD_GLYPH_STRINGS (end, i, h, t,
30808 overlap_hl, x, last_x);
30809
30810
30811 compute_overhangs_and_x (h, tail->x + tail->width, false);
30812 append_glyph_string_lists (&head, &tail, h, t);
30813 if (clip_tail == NULL)
30814 clip_tail = tail;
30815 }
30816
30817
30818
30819
30820
30821
30822 i = right_overwriting (tail);
30823 if (i >= 0)
30824 {
30825 enum draw_glyphs_face overlap_hl;
30826 if (check_mouse_face
30827 && mouse_beg_col < i && mouse_end_col > end)
30828 overlap_hl = DRAW_MOUSE_FACE;
30829 else
30830 overlap_hl = DRAW_NORMAL_TEXT;
30831
30832 if (hl == overlap_hl || clip_tail == NULL)
30833 clip_tail = tail;
30834 i++;
30835 BUILD_GLYPH_STRINGS (end, i, h, t,
30836 overlap_hl, x, last_x);
30837 for (s = h; s; s = s->next)
30838 s->background_filled_p = true;
30839 compute_overhangs_and_x (h, tail->x + tail->width, false);
30840 append_glyph_string_lists (&head, &tail, h, t);
30841 }
30842 tail = glyph_string_containing_background_width (tail);
30843 if (clip_tail)
30844 clip_tail = glyph_string_containing_background_width (clip_tail);
30845 if (clip_head || clip_tail)
30846 for (s = head; s; s = s->next)
30847 {
30848 s->clip_head = clip_head;
30849 s->clip_tail = clip_tail;
30850 }
30851 }
30852
30853
30854 for (s = head; s; s = s->next)
30855 FRAME_RIF (f)->draw_glyph_string (s);
30856
30857
30858
30859 if (area == TEXT_AREA
30860 && !row->full_width_p
30861
30862
30863
30864 && !overlaps)
30865 {
30866 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30867 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30868 : (tail ? tail->x + tail->background_width : x));
30869 x0 -= area_left;
30870 x1 -= area_left;
30871
30872 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30873 row->y, MATRIX_ROW_BOTTOM_Y (row));
30874 }
30875
30876
30877
30878 if (row->full_width_p)
30879 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30880 else
30881 x_reached -= area_left;
30882
30883 RELEASE_HDC (hdc, f);
30884
30885 SAFE_FREE ();
30886 return x_reached;
30887 }
30888
30889
30890
30891
30892
30893
30894
30895
30896 struct font *
30897 font_for_underline_metrics (struct glyph_string *s)
30898 {
30899 struct glyph *g0 = s->row->glyphs[s->area], *g;
30900
30901 for (g = s->first_glyph - 1; g >= g0; g--)
30902 {
30903 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30904 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30905 break;
30906 }
30907
30908
30909 if (g == s->first_glyph - 1)
30910 return s->font;
30911 else
30912 {
30913
30914
30915 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30916 }
30917 }
30918
30919
30920
30921
30922 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30923 { \
30924 if (!it->f->fonts_changed \
30925 && (it->glyph_row->glyphs[area] \
30926 < it->glyph_row->glyphs[area + 1])) \
30927 { \
30928 it->w->ncols_scale_factor++; \
30929 it->f->fonts_changed = true; \
30930 } \
30931 }
30932
30933
30934
30935
30936 static void
30937 append_glyph (struct it *it)
30938 {
30939 struct glyph *glyph;
30940 enum glyph_row_area area = it->area;
30941
30942 eassert (it->glyph_row);
30943 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30944
30945 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30946 if (glyph < it->glyph_row->glyphs[area + 1])
30947 {
30948
30949
30950 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30951 {
30952 struct glyph *g;
30953
30954
30955 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30956 g[1] = *g;
30957 glyph = it->glyph_row->glyphs[area];
30958 }
30959 glyph->charpos = CHARPOS (it->position);
30960 glyph->object = it->object;
30961 if (it->pixel_width > 0)
30962 {
30963 eassert (it->pixel_width <= SHRT_MAX);
30964 glyph->pixel_width = it->pixel_width;
30965 glyph->padding_p = false;
30966 }
30967 else
30968 {
30969
30970
30971 glyph->pixel_width = 1;
30972 glyph->padding_p = true;
30973 }
30974 glyph->ascent = it->ascent;
30975 glyph->descent = it->descent;
30976 glyph->voffset = it->voffset;
30977 glyph->type = CHAR_GLYPH;
30978 glyph->avoid_cursor_p = it->avoid_cursor_p;
30979 glyph->multibyte_p = it->multibyte_p;
30980 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30981 {
30982
30983
30984 glyph->right_box_line_p = it->start_of_box_run_p;
30985 glyph->left_box_line_p = it->end_of_box_run_p;
30986 }
30987 else
30988 {
30989 glyph->left_box_line_p = it->start_of_box_run_p;
30990 glyph->right_box_line_p = it->end_of_box_run_p;
30991 }
30992 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30993 || it->phys_descent > it->descent);
30994 glyph->glyph_not_available_p = it->glyph_not_available_p;
30995 glyph->face_id = it->face_id;
30996 glyph->u.ch = it->char_to_display;
30997 glyph->slice.img = null_glyph_slice;
30998 glyph->font_type = FONT_TYPE_UNKNOWN;
30999 if (it->bidi_p)
31000 {
31001 glyph->resolved_level = it->bidi_it.resolved_level;
31002 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31003 glyph->bidi_type = it->bidi_it.type;
31004 }
31005 else
31006 {
31007 glyph->resolved_level = 0;
31008 glyph->bidi_type = UNKNOWN_BT;
31009 }
31010 ++it->glyph_row->used[area];
31011 }
31012 else
31013 IT_EXPAND_MATRIX_WIDTH (it, area);
31014 }
31015
31016
31017
31018
31019 static void
31020 append_composite_glyph (struct it *it)
31021 {
31022 struct glyph *glyph;
31023 enum glyph_row_area area = it->area;
31024
31025 eassert (it->glyph_row);
31026
31027 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31028 if (glyph < it->glyph_row->glyphs[area + 1])
31029 {
31030
31031
31032 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
31033 {
31034 struct glyph *g;
31035
31036
31037 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31038 g[1] = *g;
31039 glyph = it->glyph_row->glyphs[it->area];
31040 }
31041 glyph->charpos = it->cmp_it.charpos;
31042 glyph->object = it->object;
31043 eassert (it->pixel_width <= SHRT_MAX);
31044 glyph->pixel_width = it->pixel_width;
31045 glyph->ascent = it->ascent;
31046 glyph->descent = it->descent;
31047 glyph->voffset = it->voffset;
31048 glyph->type = COMPOSITE_GLYPH;
31049 if (it->cmp_it.ch < 0)
31050 {
31051 glyph->u.cmp.automatic = false;
31052 glyph->u.cmp.id = it->cmp_it.id;
31053 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
31054 }
31055 else
31056 {
31057 glyph->u.cmp.automatic = true;
31058 glyph->u.cmp.id = it->cmp_it.id;
31059 glyph->slice.cmp.from = it->cmp_it.from;
31060 glyph->slice.cmp.to = it->cmp_it.to - 1;
31061 }
31062 glyph->avoid_cursor_p = it->avoid_cursor_p;
31063 glyph->multibyte_p = it->multibyte_p;
31064 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31065 {
31066
31067
31068 glyph->right_box_line_p = it->start_of_box_run_p;
31069 glyph->left_box_line_p = it->end_of_box_run_p;
31070 }
31071 else
31072 {
31073 glyph->left_box_line_p = it->start_of_box_run_p;
31074 glyph->right_box_line_p = it->end_of_box_run_p;
31075 }
31076 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31077 || it->phys_descent > it->descent);
31078 glyph->padding_p = false;
31079 glyph->glyph_not_available_p = it->glyph_not_available_p;
31080 glyph->face_id = it->face_id;
31081 glyph->font_type = FONT_TYPE_UNKNOWN;
31082 if (it->bidi_p)
31083 {
31084 glyph->resolved_level = it->bidi_it.resolved_level;
31085 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31086 glyph->bidi_type = it->bidi_it.type;
31087 }
31088 ++it->glyph_row->used[area];
31089 }
31090 else
31091 IT_EXPAND_MATRIX_WIDTH (it, area);
31092 }
31093
31094
31095
31096
31097
31098 static void
31099 take_vertical_position_into_account (struct it *it)
31100 {
31101 if (it->voffset)
31102 {
31103 if (it->voffset < 0)
31104
31105
31106 it->ascent -= it->voffset;
31107 else
31108
31109
31110 it->descent += it->voffset;
31111 }
31112 }
31113
31114
31115
31116
31117
31118
31119 static void
31120 produce_image_glyph (struct it *it)
31121 {
31122 struct image *img;
31123 struct face *face;
31124 int glyph_ascent, crop;
31125 struct glyph_slice slice;
31126
31127 eassert (it->what == IT_IMAGE);
31128
31129 face = FACE_FROM_ID (it->f, it->face_id);
31130
31131 prepare_face_for_display (it->f, face);
31132
31133 if (it->image_id < 0)
31134 {
31135
31136 it->ascent = it->phys_ascent = 0;
31137 it->descent = it->phys_descent = 0;
31138 it->pixel_width = 0;
31139 it->nglyphs = 0;
31140 return;
31141 }
31142
31143 img = IMAGE_FROM_ID (it->f, it->image_id);
31144
31145 prepare_image_for_display (it->f, img);
31146
31147 slice.x = slice.y = 0;
31148 slice.width = img->width;
31149 slice.height = img->height;
31150
31151 if (FIXNUMP (it->slice.x))
31152 slice.x = XFIXNUM (it->slice.x);
31153 else if (FLOATP (it->slice.x))
31154 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
31155
31156 if (FIXNUMP (it->slice.y))
31157 slice.y = XFIXNUM (it->slice.y);
31158 else if (FLOATP (it->slice.y))
31159 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
31160
31161 if (FIXNUMP (it->slice.width))
31162 slice.width = XFIXNUM (it->slice.width);
31163 else if (FLOATP (it->slice.width))
31164 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
31165
31166 if (FIXNUMP (it->slice.height))
31167 slice.height = XFIXNUM (it->slice.height);
31168 else if (FLOATP (it->slice.height))
31169 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
31170
31171 if (slice.x >= img->width)
31172 slice.x = img->width;
31173 if (slice.y >= img->height)
31174 slice.y = img->height;
31175 if (slice.x + slice.width >= img->width)
31176 slice.width = img->width - slice.x;
31177 if (slice.y + slice.height > img->height)
31178 slice.height = img->height - slice.y;
31179
31180 if (slice.width == 0 || slice.height == 0)
31181 return;
31182
31183 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
31184
31185 it->descent = slice.height - glyph_ascent;
31186 if (slice.y == 0)
31187 it->descent += img->vmargin;
31188 if (slice.y + slice.height == img->height)
31189 it->descent += img->vmargin;
31190 it->phys_descent = it->descent;
31191
31192 it->pixel_width = slice.width;
31193 if (slice.x == 0)
31194 it->pixel_width += img->hmargin;
31195 if (slice.x + slice.width == img->width)
31196 it->pixel_width += img->hmargin;
31197
31198
31199
31200 if (it->descent < 0)
31201 it->descent = 0;
31202
31203 it->nglyphs = 1;
31204
31205 if (face->box != FACE_NO_BOX)
31206 {
31207
31208
31209 if (face->box_horizontal_line_width > 0)
31210 {
31211 if (slice.y == 0)
31212 it->ascent += face->box_horizontal_line_width;
31213 if (slice.y + slice.height == img->height)
31214 it->descent += face->box_horizontal_line_width;
31215 }
31216
31217 if (face->box_vertical_line_width > 0)
31218 {
31219 if (it->start_of_box_run_p && slice.x == 0)
31220 it->pixel_width += face->box_vertical_line_width;
31221 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31222 it->pixel_width += face->box_vertical_line_width;
31223 }
31224 }
31225
31226 take_vertical_position_into_account (it);
31227
31228
31229
31230 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31231 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31232 {
31233 it->pixel_width -= crop;
31234 slice.width -= crop;
31235 }
31236
31237 if (it->glyph_row)
31238 {
31239 struct glyph *glyph;
31240 enum glyph_row_area area = it->area;
31241
31242 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31243 if (it->glyph_row->reversed_p)
31244 {
31245 struct glyph *g;
31246
31247
31248 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31249 g[1] = *g;
31250 glyph = it->glyph_row->glyphs[it->area];
31251 }
31252 if (glyph < it->glyph_row->glyphs[area + 1])
31253 {
31254 glyph->charpos = CHARPOS (it->position);
31255 glyph->object = it->object;
31256 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31257 glyph->ascent = glyph_ascent;
31258 glyph->descent = it->descent;
31259 glyph->voffset = it->voffset;
31260 glyph->type = IMAGE_GLYPH;
31261 glyph->avoid_cursor_p = it->avoid_cursor_p;
31262 glyph->multibyte_p = it->multibyte_p;
31263 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31264 {
31265
31266
31267 glyph->right_box_line_p = it->start_of_box_run_p;
31268 glyph->left_box_line_p = it->end_of_box_run_p;
31269 }
31270 else
31271 {
31272 glyph->left_box_line_p = it->start_of_box_run_p;
31273 glyph->right_box_line_p = it->end_of_box_run_p;
31274 }
31275 glyph->overlaps_vertically_p = false;
31276 glyph->padding_p = false;
31277 glyph->glyph_not_available_p = false;
31278 glyph->face_id = it->face_id;
31279 glyph->u.img_id = img->id;
31280 glyph->slice.img = slice;
31281 glyph->font_type = FONT_TYPE_UNKNOWN;
31282 if (it->bidi_p)
31283 {
31284 glyph->resolved_level = it->bidi_it.resolved_level;
31285 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31286 glyph->bidi_type = it->bidi_it.type;
31287 }
31288 ++it->glyph_row->used[area];
31289 }
31290 else
31291 IT_EXPAND_MATRIX_WIDTH (it, area);
31292 }
31293 }
31294
31295 static void
31296 produce_xwidget_glyph (struct it *it)
31297 {
31298 #ifdef HAVE_XWIDGETS
31299 struct xwidget *xw;
31300 int glyph_ascent, crop;
31301 eassert (it->what == IT_XWIDGET);
31302
31303 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31304
31305 prepare_face_for_display (it->f, face);
31306
31307 xw = it->xwidget;
31308 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31309 it->descent = xw->height/2;
31310 it->phys_descent = it->descent;
31311 it->pixel_width = xw->width;
31312
31313
31314 if (it->descent < 0)
31315 it->descent = 0;
31316
31317 it->nglyphs = 1;
31318
31319 if (face->box != FACE_NO_BOX)
31320 {
31321 if (face->box_horizontal_line_width > 0)
31322 {
31323 it->ascent += face->box_horizontal_line_width;
31324 it->descent += face->box_horizontal_line_width;
31325 }
31326
31327 if (face->box_vertical_line_width > 0)
31328 {
31329 if (it->start_of_box_run_p)
31330 it->pixel_width += face->box_vertical_line_width;
31331 it->pixel_width += face->box_vertical_line_width;
31332 }
31333 }
31334
31335 take_vertical_position_into_account (it);
31336
31337
31338
31339 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31340 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31341 it->pixel_width -= crop;
31342
31343 if (it->glyph_row)
31344 {
31345 enum glyph_row_area area = it->area;
31346 struct glyph *glyph
31347 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31348
31349 if (it->glyph_row->reversed_p)
31350 {
31351 struct glyph *g;
31352
31353
31354 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31355 g[1] = *g;
31356 glyph = it->glyph_row->glyphs[it->area];
31357 }
31358 if (glyph < it->glyph_row->glyphs[area + 1])
31359 {
31360 glyph->charpos = CHARPOS (it->position);
31361 glyph->object = it->object;
31362 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31363 glyph->ascent = glyph_ascent;
31364 glyph->descent = it->descent;
31365 glyph->voffset = it->voffset;
31366 glyph->type = XWIDGET_GLYPH;
31367 glyph->avoid_cursor_p = it->avoid_cursor_p;
31368 glyph->multibyte_p = it->multibyte_p;
31369 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31370 {
31371
31372
31373 glyph->right_box_line_p = it->start_of_box_run_p;
31374 glyph->left_box_line_p = it->end_of_box_run_p;
31375 }
31376 else
31377 {
31378 glyph->left_box_line_p = it->start_of_box_run_p;
31379 glyph->right_box_line_p = it->end_of_box_run_p;
31380 }
31381 glyph->overlaps_vertically_p = 0;
31382 glyph->padding_p = 0;
31383 glyph->glyph_not_available_p = 0;
31384 glyph->face_id = it->face_id;
31385 glyph->u.xwidget = it->xwidget->xwidget_id;
31386 glyph->font_type = FONT_TYPE_UNKNOWN;
31387 if (it->bidi_p)
31388 {
31389 glyph->resolved_level = it->bidi_it.resolved_level;
31390 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31391 glyph->bidi_type = it->bidi_it.type;
31392 }
31393 ++it->glyph_row->used[area];
31394 }
31395 else
31396 IT_EXPAND_MATRIX_WIDTH (it, area);
31397 }
31398 #endif
31399 }
31400
31401
31402
31403
31404
31405 static void
31406 append_stretch_glyph (struct it *it, Lisp_Object object,
31407 int width, int height, int ascent)
31408 {
31409 struct glyph *glyph;
31410 enum glyph_row_area area = it->area;
31411
31412 eassert (ascent >= 0 && ascent <= height);
31413
31414 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31415 if (glyph < it->glyph_row->glyphs[area + 1])
31416 {
31417
31418
31419 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31420 {
31421 struct glyph *g;
31422
31423
31424 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31425 g[1] = *g;
31426 glyph = it->glyph_row->glyphs[area];
31427
31428
31429
31430
31431
31432
31433
31434
31435
31436
31437
31438
31439
31440
31441
31442 if (it->current_x < it->first_visible_x)
31443 width -= it->first_visible_x - it->current_x;
31444 eassert (width > 0);
31445 }
31446 glyph->charpos = CHARPOS (it->position);
31447 glyph->object = object;
31448
31449
31450 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31451 glyph->ascent = ascent;
31452 glyph->descent = height - ascent;
31453 glyph->voffset = it->voffset;
31454 glyph->type = STRETCH_GLYPH;
31455 glyph->avoid_cursor_p = it->avoid_cursor_p;
31456 glyph->multibyte_p = it->multibyte_p;
31457 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31458 {
31459
31460
31461 glyph->right_box_line_p = it->start_of_box_run_p;
31462 glyph->left_box_line_p = it->end_of_box_run_p;
31463 }
31464 else
31465 {
31466 glyph->left_box_line_p = it->start_of_box_run_p;
31467 glyph->right_box_line_p = it->end_of_box_run_p;
31468 }
31469 glyph->overlaps_vertically_p = false;
31470 glyph->padding_p = false;
31471 glyph->glyph_not_available_p = false;
31472 glyph->face_id = it->face_id;
31473 glyph->u.stretch.ascent = ascent;
31474 glyph->u.stretch.height = height;
31475 glyph->slice.img = null_glyph_slice;
31476 glyph->font_type = FONT_TYPE_UNKNOWN;
31477 if (it->bidi_p)
31478 {
31479 glyph->resolved_level = it->bidi_it.resolved_level;
31480 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31481 glyph->bidi_type = it->bidi_it.type;
31482 }
31483 else
31484 {
31485 glyph->resolved_level = 0;
31486 glyph->bidi_type = UNKNOWN_BT;
31487 }
31488 ++it->glyph_row->used[area];
31489 }
31490 else
31491 IT_EXPAND_MATRIX_WIDTH (it, area);
31492 }
31493
31494 #endif
31495
31496
31497
31498
31499
31500
31501
31502
31503
31504
31505
31506
31507
31508
31509
31510
31511
31512
31513
31514
31515
31516
31517
31518
31519
31520
31521
31522
31523
31524
31525
31526
31527 void
31528 produce_stretch_glyph (struct it *it)
31529 {
31530
31531 Lisp_Object prop, plist;
31532 int width = 0, height = 0, align_to = -1;
31533 bool zero_width_ok_p = false;
31534 double tem;
31535 struct font *font = NULL;
31536
31537 #ifdef HAVE_WINDOW_SYSTEM
31538 int ascent = 0;
31539 bool zero_height_ok_p = false;
31540 struct face *face = NULL;
31541
31542 if (FRAME_WINDOW_P (it->f))
31543 {
31544 face = FACE_FROM_ID (it->f, it->face_id);
31545 font = face->font ? face->font : FRAME_FONT (it->f);
31546 prepare_face_for_display (it->f, face);
31547 }
31548 #endif
31549
31550
31551 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31552 plist = XCDR (it->object);
31553
31554
31555 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31556 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31557 {
31558
31559 zero_width_ok_p = true;
31560 width = (int)tem;
31561 }
31562 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31563 {
31564
31565
31566
31567 struct it it2;
31568 Lisp_Object object =
31569 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31570 unsigned char *p = (STRINGP (object)
31571 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31572 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31573 bool multibyte_p =
31574 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31575
31576 it2 = *it;
31577 if (multibyte_p)
31578 {
31579 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31580 #ifdef HAVE_WINDOW_SYSTEM
31581 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31582 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31583 IT_CHARPOS (*it),
31584 STRINGP (object)? object : Qnil);
31585 #endif
31586 }
31587 else
31588 {
31589 it2.c = it2.char_to_display = *p, it2.len = 1;
31590 if (! ASCII_CHAR_P (it2.c))
31591 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31592 }
31593
31594 it2.glyph_row = NULL;
31595 it2.what = IT_CHARACTER;
31596 PRODUCE_GLYPHS (&it2);
31597 width = NUMVAL (prop) * it2.pixel_width;
31598 }
31599 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31600 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31601 &align_to))
31602 {
31603 int x = it->current_x + it->continuation_lines_width;
31604 int x0 = x;
31605
31606 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31607 {
31608 x -= it->lnum_pixel_width;
31609
31610 if (x + it->stretch_adjust >= it->first_visible_x)
31611 x += it->stretch_adjust;
31612 }
31613
31614 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31615 align_to = (align_to < 0
31616 ? 0
31617 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31618 else if (align_to < 0)
31619 align_to = window_box_left_offset (it->w, TEXT_AREA);
31620 width = max (0, (int)tem + align_to - x);
31621
31622 int next_x = x + width;
31623 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31624 {
31625
31626
31627 if (x < it->first_visible_x)
31628 {
31629 next_x -= it->first_visible_x - x;
31630 it->stretch_adjust = it->first_visible_x - x;
31631 }
31632 else
31633 next_x -= it->stretch_adjust;
31634 }
31635 width = next_x - x0;
31636 zero_width_ok_p = true;
31637 }
31638 else
31639
31640 width = FRAME_COLUMN_WIDTH (it->f);
31641
31642 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31643 width = 1;
31644
31645 #ifdef HAVE_WINDOW_SYSTEM
31646
31647 if (FRAME_WINDOW_P (it->f))
31648 {
31649 int default_height = normal_char_height (font, ' ');
31650
31651 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31652 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31653 {
31654 height = (int)tem;
31655 zero_height_ok_p = true;
31656 }
31657 else if (prop = plist_get (plist, QCrelative_height),
31658 NUMVAL (prop) > 0)
31659 height = default_height * NUMVAL (prop);
31660 else
31661 height = default_height;
31662
31663 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31664 height = 1;
31665
31666
31667
31668
31669 if (prop = plist_get (plist, QCascent),
31670 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31671 ascent = height * NUMVAL (prop) / 100.0;
31672 else if (!NILP (prop)
31673 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31674 ascent = min (max (0, (int)tem), height);
31675 else
31676 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31677 }
31678 else
31679 #endif
31680 height = 1;
31681
31682 if (width > 0
31683 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31684 && it->current_x + width > it->last_visible_x)
31685 {
31686 width = it->last_visible_x - it->current_x;
31687 #ifdef HAVE_WINDOW_SYSTEM
31688
31689
31690 width -= FRAME_WINDOW_P (it->f);
31691 #endif
31692 }
31693
31694 if (width > 0 && height > 0 && it->glyph_row)
31695 {
31696 Lisp_Object o_object = it->object;
31697 Lisp_Object object =
31698 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31699 int n = width;
31700
31701 if (!STRINGP (object))
31702 object = it->w->contents;
31703 #ifdef HAVE_WINDOW_SYSTEM
31704 if (FRAME_WINDOW_P (it->f))
31705 append_stretch_glyph (it, object, width, height, ascent);
31706 else
31707 #endif
31708 {
31709 it->object = object;
31710 it->char_to_display = ' ';
31711 it->pixel_width = it->len = 1;
31712 while (n--)
31713 tty_append_glyph (it);
31714 it->object = o_object;
31715 }
31716 }
31717
31718 it->pixel_width = width;
31719 #ifdef HAVE_WINDOW_SYSTEM
31720 if (FRAME_WINDOW_P (it->f))
31721 {
31722 it->ascent = it->phys_ascent = ascent;
31723 it->descent = it->phys_descent = height - it->ascent;
31724 it->nglyphs = width > 0 && height > 0;
31725 take_vertical_position_into_account (it);
31726 }
31727 else
31728 #endif
31729 it->nglyphs = width;
31730 }
31731
31732
31733
31734
31735
31736
31737
31738 static void
31739 produce_special_glyphs (struct it *it, enum display_element_type what)
31740 {
31741 struct it temp_it;
31742 Lisp_Object gc;
31743 GLYPH glyph;
31744
31745 temp_it = *it;
31746 temp_it.object = Qnil;
31747 memset (&temp_it.current, 0, sizeof temp_it.current);
31748
31749 if (what == IT_CONTINUATION)
31750 {
31751
31752 if (it->bidi_it.paragraph_dir == R2L)
31753 SET_GLYPH_FROM_CHAR (glyph, '/');
31754 else
31755 SET_GLYPH_FROM_CHAR (glyph, '\\');
31756 if (it->dp
31757 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31758 {
31759
31760 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31761 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31762 }
31763 }
31764 else if (what == IT_TRUNCATION)
31765 {
31766
31767 SET_GLYPH_FROM_CHAR (glyph, '$');
31768 if (it->dp
31769 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31770 {
31771
31772 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31773 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31774 }
31775 }
31776 else
31777 emacs_abort ();
31778
31779 #ifdef HAVE_WINDOW_SYSTEM
31780
31781
31782
31783
31784
31785 if (FRAME_WINDOW_P (temp_it.f)
31786
31787
31788
31789 && temp_it.glyph_row
31790
31791
31792
31793 && temp_it.glyph_row->used[TEXT_AREA] > 0
31794 && (temp_it.glyph_row->reversed_p
31795 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31796 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31797 {
31798 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31799
31800 if (stretch_width > 0)
31801 {
31802 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31803 struct font *font =
31804 face->font ? face->font : FRAME_FONT (temp_it.f);
31805 int stretch_ascent =
31806 (((temp_it.ascent + temp_it.descent)
31807 * FONT_BASE (font)) / FONT_HEIGHT (font));
31808
31809 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31810 temp_it.ascent + temp_it.descent,
31811 stretch_ascent);
31812 }
31813 }
31814 #endif
31815
31816 temp_it.dp = NULL;
31817 temp_it.what = IT_CHARACTER;
31818 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31819 temp_it.face_id = GLYPH_FACE (glyph);
31820 temp_it.len = CHAR_BYTES (temp_it.c);
31821
31822 PRODUCE_GLYPHS (&temp_it);
31823 it->pixel_width = temp_it.pixel_width;
31824 it->nglyphs = temp_it.nglyphs;
31825 }
31826
31827
31828
31829
31830
31831
31832
31833
31834
31835 static void
31836 pad_mode_line (struct it *it, bool mode_line_p)
31837 {
31838 struct it temp_it;
31839 GLYPH glyph;
31840
31841 eassert (!FRAME_WINDOW_P (it->f));
31842 temp_it = *it;
31843 temp_it.object = Qnil;
31844 memset (&temp_it.current, 0, sizeof temp_it.current);
31845
31846 SET_GLYPH (glyph, mode_line_p ? '-' : ' ', it->base_face_id);
31847
31848 temp_it.dp = NULL;
31849 temp_it.what = IT_CHARACTER;
31850 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31851 temp_it.face_id = GLYPH_FACE (glyph);
31852 temp_it.len = CHAR_BYTES (temp_it.c);
31853
31854 PRODUCE_GLYPHS (&temp_it);
31855 it->pixel_width = temp_it.pixel_width;
31856 it->nglyphs = temp_it.nglyphs;
31857 }
31858
31859 #ifdef HAVE_WINDOW_SYSTEM
31860
31861
31862
31863
31864
31865
31866
31867
31868
31869 static Lisp_Object
31870 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31871 int boff, bool override)
31872 {
31873 Lisp_Object face_name = Qnil;
31874 int ascent, descent, height;
31875
31876 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31877 return val;
31878
31879 if (CONSP (val))
31880 {
31881 face_name = XCAR (val);
31882 val = XCDR (val);
31883 if (!NUMBERP (val))
31884 val = make_fixnum (1);
31885 if (NILP (face_name))
31886 {
31887 height = it->ascent + it->descent;
31888 goto scale;
31889 }
31890 }
31891
31892 if (NILP (face_name))
31893 {
31894 font = FRAME_FONT (it->f);
31895 boff = FRAME_BASELINE_OFFSET (it->f);
31896 }
31897 else if (EQ (face_name, Qt))
31898 {
31899 override = false;
31900 }
31901 else
31902 {
31903 int face_id;
31904 struct face *face;
31905
31906 face_id = lookup_named_face (it->w, it->f, face_name, false);
31907 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31908 if (face == NULL || ((font = face->font) == NULL))
31909 return make_fixnum (-1);
31910 boff = font->baseline_offset;
31911 if (font->vertical_centering)
31912 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31913 }
31914
31915 normal_char_ascent_descent (font, -1, &ascent, &descent);
31916
31917 if (override)
31918 {
31919 it->override_ascent = ascent;
31920 it->override_descent = descent;
31921 it->override_boff = boff;
31922 }
31923
31924 height = ascent + descent;
31925
31926 scale:
31927
31928 if (FLOATP (val))
31929 height = (int)(XFLOAT_DATA (val) * height);
31930 else if (INTEGERP (val))
31931 {
31932 intmax_t v;
31933 if (integer_to_intmax (val, &v))
31934 height *= v;
31935 }
31936
31937 return make_fixnum (height);
31938 }
31939
31940
31941
31942
31943
31944
31945
31946
31947
31948
31949
31950
31951
31952
31953 static void
31954 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31955 short upper_xoff, short upper_yoff,
31956 short lower_xoff, short lower_yoff)
31957 {
31958 struct glyph *glyph;
31959 enum glyph_row_area area = it->area;
31960
31961 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31962 if (glyph < it->glyph_row->glyphs[area + 1])
31963 {
31964
31965
31966 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31967 {
31968 struct glyph *g;
31969
31970
31971 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31972 g[1] = *g;
31973 glyph = it->glyph_row->glyphs[area];
31974 }
31975 glyph->charpos = CHARPOS (it->position);
31976 glyph->object = it->object;
31977 eassert (it->pixel_width <= SHRT_MAX);
31978 glyph->pixel_width = it->pixel_width;
31979 glyph->ascent = it->ascent;
31980 glyph->descent = it->descent;
31981 glyph->voffset = it->voffset;
31982 glyph->type = GLYPHLESS_GLYPH;
31983 glyph->u.glyphless.method = it->glyphless_method;
31984 glyph->u.glyphless.for_no_font = for_no_font;
31985 glyph->u.glyphless.len = len;
31986 glyph->u.glyphless.ch = it->c;
31987 glyph->slice.glyphless.upper_xoff = upper_xoff;
31988 glyph->slice.glyphless.upper_yoff = upper_yoff;
31989 glyph->slice.glyphless.lower_xoff = lower_xoff;
31990 glyph->slice.glyphless.lower_yoff = lower_yoff;
31991 glyph->avoid_cursor_p = it->avoid_cursor_p;
31992 glyph->multibyte_p = it->multibyte_p;
31993 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31994 {
31995
31996
31997 glyph->right_box_line_p = it->start_of_box_run_p;
31998 glyph->left_box_line_p = it->end_of_box_run_p;
31999 }
32000 else
32001 {
32002 glyph->left_box_line_p = it->start_of_box_run_p;
32003 glyph->right_box_line_p = it->end_of_box_run_p;
32004 }
32005 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
32006 || it->phys_descent > it->descent);
32007 glyph->padding_p = false;
32008 glyph->glyph_not_available_p = false;
32009 glyph->face_id = face_id;
32010 glyph->font_type = FONT_TYPE_UNKNOWN;
32011 if (it->bidi_p)
32012 {
32013 glyph->resolved_level = it->bidi_it.resolved_level;
32014 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
32015 glyph->bidi_type = it->bidi_it.type;
32016 }
32017 ++it->glyph_row->used[area];
32018 }
32019 else
32020 IT_EXPAND_MATRIX_WIDTH (it, area);
32021 }
32022
32023
32024
32025
32026
32027
32028
32029
32030
32031
32032
32033 static void
32034 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
32035 {
32036 int face_id;
32037 struct face *face;
32038 struct font *font;
32039 int base_width, base_height, width, height;
32040 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
32041 int len;
32042
32043
32044
32045 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
32046 font = face->font ? face->font : FRAME_FONT (it->f);
32047 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
32048 it->ascent += font->baseline_offset;
32049 it->descent -= font->baseline_offset;
32050 base_height = it->ascent + it->descent;
32051 base_width = font->average_width;
32052
32053 face_id = merge_glyphless_glyph_face (it);
32054
32055 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
32056 {
32057 it->pixel_width = THIN_SPACE_WIDTH;
32058 len = 0;
32059 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32060 }
32061 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
32062 {
32063 width = CHARACTER_WIDTH (it->c);
32064 if (width == 0)
32065 width = 1;
32066 else if (width > 4)
32067 width = 4;
32068 it->pixel_width = base_width * width;
32069 len = 0;
32070 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32071 }
32072 else
32073 {
32074 char buf[7];
32075 const char *str;
32076 unsigned int code[6];
32077 int upper_len;
32078 int ascent, descent;
32079 struct font_metrics metrics_upper, metrics_lower;
32080
32081 face = FACE_FROM_ID (it->f, face_id);
32082 font = face->font ? face->font : FRAME_FONT (it->f);
32083 prepare_face_for_display (it->f, face);
32084
32085 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
32086 {
32087 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
32088 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
32089 if (CONSP (acronym))
32090 acronym = XCAR (acronym);
32091 str = STRINGP (acronym) ? SSDATA (acronym) : "";
32092 }
32093 else
32094 {
32095 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
32096 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
32097 str = buf;
32098 }
32099 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
32100 code[len] = font->driver->encode_char (font, str[len]);
32101 upper_len = (len + 1) / 2;
32102 font->driver->text_extents (font, code, upper_len,
32103 &metrics_upper);
32104 font->driver->text_extents (font, code + upper_len, len - upper_len,
32105 &metrics_lower);
32106
32107
32108
32109
32110 width = max (metrics_upper.width, metrics_lower.width) + 4;
32111 upper_xoff = lower_xoff = 2;
32112 if (base_width >= width)
32113 {
32114
32115 it->pixel_width = base_width;
32116 lower_xoff = base_width - 2 - metrics_lower.width;
32117 }
32118 else
32119 {
32120
32121 it->pixel_width = width;
32122 if (metrics_upper.width >= metrics_lower.width)
32123 lower_xoff = (width - metrics_lower.width) / 2;
32124 else
32125 upper_xoff = (width - metrics_upper.width) / 2;
32126 }
32127
32128
32129
32130 height = (metrics_upper.ascent + metrics_upper.descent
32131 + metrics_lower.ascent + metrics_lower.descent) + 5;
32132
32133
32134
32135
32136
32137
32138
32139
32140 ascent = - (it->descent - (base_height + height + 1) / 2);
32141 descent = it->descent - (base_height - height) / 2;
32142 lower_yoff = descent - 2 - metrics_lower.descent;
32143 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
32144 - metrics_upper.descent);
32145
32146 if (height > base_height)
32147 {
32148 it->ascent = ascent;
32149 it->descent = descent;
32150 }
32151 }
32152
32153 it->phys_ascent = it->ascent;
32154 it->phys_descent = it->descent;
32155 if (it->glyph_row)
32156 append_glyphless_glyph (it, face_id, for_no_font, len,
32157 upper_xoff, upper_yoff,
32158 lower_xoff, lower_yoff);
32159 it->nglyphs = 1;
32160 take_vertical_position_into_account (it);
32161 }
32162
32163
32164
32165
32166
32167 #define IT_APPLY_FACE_BOX(it, face) \
32168 do { \
32169 if (face->box != FACE_NO_BOX) \
32170 { \
32171 int thick = face->box_horizontal_line_width; \
32172 if (thick > 0) \
32173 { \
32174 it->ascent += thick; \
32175 it->descent += thick; \
32176 } \
32177 \
32178 thick = face->box_vertical_line_width; \
32179 if (thick > 0) \
32180 { \
32181 if (it->start_of_box_run_p) \
32182 it->pixel_width += thick; \
32183 if (it->end_of_box_run_p) \
32184 it->pixel_width += thick; \
32185 } \
32186 } \
32187 } while (false)
32188
32189
32190
32191
32192
32193
32194 void
32195 gui_produce_glyphs (struct it *it)
32196 {
32197 int extra_line_spacing = it->extra_line_spacing;
32198
32199 it->glyph_not_available_p = false;
32200
32201 if (it->what == IT_CHARACTER)
32202 {
32203 unsigned char2b;
32204 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32205 struct font *font = face->font;
32206 struct font_metrics *pcm = NULL;
32207 int boff;
32208
32209 if (font == NULL)
32210 {
32211
32212
32213
32214 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
32215
32216 eassert (it->what == IT_GLYPHLESS);
32217 produce_glyphless_glyph (it, true,
32218 STRINGP (acronym) ? acronym : Qnil);
32219 goto done;
32220 }
32221
32222 boff = font->baseline_offset;
32223 if (font->vertical_centering)
32224 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32225
32226 if (it->char_to_display != '\n' && it->char_to_display != '\t')
32227 {
32228 it->nglyphs = 1;
32229
32230 if (it->override_ascent >= 0)
32231 {
32232 it->ascent = it->override_ascent;
32233 it->descent = it->override_descent;
32234 boff = it->override_boff;
32235 }
32236 else
32237 {
32238 it->ascent = FONT_BASE (font) + boff;
32239 it->descent = FONT_DESCENT (font) - boff;
32240 }
32241
32242 if (get_char_glyph_code (it->char_to_display, font, &char2b))
32243 {
32244 pcm = get_per_char_metric (font, &char2b);
32245 if (pcm->width == 0
32246 && pcm->rbearing == 0 && pcm->lbearing == 0)
32247 pcm = NULL;
32248 }
32249
32250 if (pcm)
32251 {
32252 it->phys_ascent = pcm->ascent + boff;
32253 it->phys_descent = pcm->descent - boff;
32254 it->pixel_width = pcm->width;
32255
32256
32257 if (it->override_ascent < 0)
32258 {
32259 if (FONT_TOO_HIGH (font))
32260 {
32261 it->ascent = it->phys_ascent;
32262 it->descent = it->phys_descent;
32263
32264
32265 if (it->ascent < 0)
32266 it->ascent = 0;
32267 if (it->descent < 0)
32268 it->descent = 0;
32269 }
32270 }
32271 }
32272 else
32273 {
32274 it->glyph_not_available_p = true;
32275 it->phys_ascent = it->ascent;
32276 it->phys_descent = it->descent;
32277 it->pixel_width = font->space_width;
32278 }
32279
32280 if (it->constrain_row_ascent_descent_p)
32281 {
32282 if (it->descent > it->max_descent)
32283 {
32284 it->ascent += it->descent - it->max_descent;
32285 it->descent = it->max_descent;
32286 }
32287 if (it->ascent > it->max_ascent)
32288 {
32289 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32290 it->ascent = it->max_ascent;
32291 }
32292 it->phys_ascent = min (it->phys_ascent, it->ascent);
32293 it->phys_descent = min (it->phys_descent, it->descent);
32294 extra_line_spacing = 0;
32295 }
32296
32297
32298
32299 bool stretched_p
32300 = it->char_to_display == ' ' && !NILP (it->space_width);
32301 if (stretched_p)
32302 it->pixel_width *= XFLOATINT (it->space_width);
32303
32304 IT_APPLY_FACE_BOX(it, face);
32305
32306
32307
32308 if (face->overline_p)
32309 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32310
32311 if (it->constrain_row_ascent_descent_p)
32312 {
32313 if (it->ascent > it->max_ascent)
32314 it->ascent = it->max_ascent;
32315 if (it->descent > it->max_descent)
32316 it->descent = it->max_descent;
32317 }
32318
32319 take_vertical_position_into_account (it);
32320
32321
32322 if (it->glyph_row)
32323 {
32324 if (stretched_p)
32325 {
32326
32327
32328 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32329 / FONT_HEIGHT (font));
32330 append_stretch_glyph (it, it->object, it->pixel_width,
32331 it->ascent + it->descent, ascent);
32332 }
32333 else
32334 append_glyph (it);
32335
32336
32337
32338
32339 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32340 it->glyph_row->contains_overlapping_glyphs_p = true;
32341 }
32342 if (! stretched_p && it->pixel_width == 0)
32343
32344
32345 it->pixel_width = 1;
32346 }
32347 else if (it->char_to_display == '\n')
32348 {
32349
32350
32351
32352
32353 Lisp_Object height;
32354 Lisp_Object total_height = Qnil;
32355
32356 it->override_ascent = -1;
32357 it->pixel_width = 0;
32358 it->nglyphs = 0;
32359
32360 height = get_it_property (it, Qline_height);
32361
32362 if (CONSP (height)
32363 && CONSP (XCDR (height))
32364 && NILP (XCDR (XCDR (height))))
32365 {
32366 total_height = XCAR (XCDR (height));
32367 height = XCAR (height);
32368 }
32369 height = calc_line_height_property (it, height, font, boff, true);
32370
32371 if (it->override_ascent >= 0)
32372 {
32373 it->ascent = it->override_ascent;
32374 it->descent = it->override_descent;
32375 boff = it->override_boff;
32376 }
32377 else
32378 {
32379 if (FONT_TOO_HIGH (font))
32380 {
32381 it->ascent = font->pixel_size + boff - 1;
32382 it->descent = -boff + 1;
32383 if (it->descent < 0)
32384 it->descent = 0;
32385 }
32386 else
32387 {
32388 it->ascent = FONT_BASE (font) + boff;
32389 it->descent = FONT_DESCENT (font) - boff;
32390 }
32391 }
32392
32393 if (EQ (height, Qt))
32394 {
32395 if (it->descent > it->max_descent)
32396 {
32397 it->ascent += it->descent - it->max_descent;
32398 it->descent = it->max_descent;
32399 }
32400 if (it->ascent > it->max_ascent)
32401 {
32402 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32403 it->ascent = it->max_ascent;
32404 }
32405 it->phys_ascent = min (it->phys_ascent, it->ascent);
32406 it->phys_descent = min (it->phys_descent, it->descent);
32407 it->constrain_row_ascent_descent_p = true;
32408 extra_line_spacing = 0;
32409 }
32410 else
32411 {
32412 Lisp_Object spacing;
32413
32414 it->phys_ascent = it->ascent;
32415 it->phys_descent = it->descent;
32416
32417 if ((it->max_ascent > 0 || it->max_descent > 0)
32418 && face->box != FACE_NO_BOX
32419 && face->box_horizontal_line_width > 0)
32420 {
32421 it->ascent += face->box_horizontal_line_width;
32422 it->descent += face->box_horizontal_line_width;
32423 }
32424 if (!NILP (height)
32425 && XFIXNUM (height) > it->ascent + it->descent)
32426 it->ascent = XFIXNUM (height) - it->descent;
32427
32428 if (!NILP (total_height))
32429 spacing = calc_line_height_property (it, total_height, font,
32430 boff, false);
32431 else
32432 {
32433 spacing = get_it_property (it, Qline_spacing);
32434 spacing = calc_line_height_property (it, spacing, font,
32435 boff, false);
32436 }
32437 if (FIXNUMP (spacing))
32438 {
32439 extra_line_spacing = XFIXNUM (spacing);
32440 if (!NILP (total_height))
32441 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32442 }
32443 }
32444 }
32445 else
32446 {
32447 if (font->space_width > 0)
32448 {
32449 int tab_width = it->tab_width * font->space_width;
32450 int x = it->current_x + it->continuation_lines_width;
32451 int x0 = x;
32452
32453 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32454 {
32455 x -= it->lnum_pixel_width;
32456
32457 if (x + it->stretch_adjust >= it->first_visible_x)
32458 x += it->stretch_adjust;
32459 }
32460
32461 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32462
32463
32464
32465
32466 if (next_tab_x - x < font->space_width)
32467 next_tab_x += tab_width;
32468 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32469 {
32470 next_tab_x += it->lnum_pixel_width;
32471
32472
32473 if (x < it->first_visible_x)
32474 {
32475 next_tab_x -= it->first_visible_x - x;
32476 it->stretch_adjust = it->first_visible_x - x;
32477 }
32478 else
32479 next_tab_x -= it->stretch_adjust;
32480 }
32481
32482 it->pixel_width = next_tab_x - x0;
32483 it->nglyphs = 1;
32484 if (FONT_TOO_HIGH (font))
32485 {
32486 if (get_char_glyph_code (' ', font, &char2b))
32487 {
32488 pcm = get_per_char_metric (font, &char2b);
32489 if (pcm->width == 0
32490 && pcm->rbearing == 0 && pcm->lbearing == 0)
32491 pcm = NULL;
32492 }
32493
32494 if (pcm)
32495 {
32496 it->ascent = pcm->ascent + boff;
32497 it->descent = pcm->descent - boff;
32498 }
32499 else
32500 {
32501 it->ascent = font->pixel_size + boff - 1;
32502 it->descent = -boff + 1;
32503 }
32504 if (it->ascent < 0)
32505 it->ascent = 0;
32506 if (it->descent < 0)
32507 it->descent = 0;
32508 }
32509 else
32510 {
32511 it->ascent = FONT_BASE (font) + boff;
32512 it->descent = FONT_DESCENT (font) - boff;
32513 }
32514 it->phys_ascent = it->ascent;
32515 it->phys_descent = it->descent;
32516
32517 if (it->glyph_row)
32518 {
32519 append_stretch_glyph (it, it->object, it->pixel_width,
32520 it->ascent + it->descent, it->ascent);
32521 }
32522 }
32523 else
32524 {
32525 it->pixel_width = 0;
32526 it->nglyphs = 1;
32527 }
32528 }
32529
32530 if (FONT_TOO_HIGH (font))
32531 {
32532 int font_ascent, font_descent;
32533
32534
32535
32536
32537
32538
32539
32540
32541 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32542 it->max_ascent = max (it->max_ascent, font_ascent);
32543 it->max_descent = max (it->max_descent, font_descent);
32544 }
32545
32546 if (it->ascent < 0)
32547 it->ascent = 0;
32548 if (it->descent < 0)
32549 it->descent = 0;
32550 }
32551 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32552 {
32553
32554
32555
32556
32557
32558
32559
32560
32561 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32562 int boff;
32563 struct composition *cmp = composition_table[it->cmp_it.id];
32564 int glyph_len = cmp->glyph_len;
32565 struct font *font = face->font;
32566
32567 it->nglyphs = 1;
32568
32569
32570
32571
32572
32573
32574
32575
32576 if (! cmp->font || cmp->font != font)
32577 {
32578
32579
32580
32581
32582 int font_ascent, font_descent, font_height;
32583
32584 int leftmost, rightmost, lowest, highest;
32585 int lbearing, rbearing;
32586 int i, width, ascent, descent;
32587 int c;
32588 unsigned char2b;
32589 struct font_metrics *pcm;
32590 ptrdiff_t pos;
32591
32592 eassume (0 < glyph_len);
32593 do
32594 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32595 while (c == '\t' && 0 < --glyph_len);
32596
32597 bool right_padded = glyph_len < cmp->glyph_len;
32598 for (i = 0; i < glyph_len; i++)
32599 {
32600 c = COMPOSITION_GLYPH (cmp, i);
32601 if (c != '\t')
32602 break;
32603 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32604 }
32605 bool left_padded = i > 0;
32606
32607 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32608 : IT_CHARPOS (*it));
32609
32610 bool font_not_found_p = font == NULL;
32611 if (font_not_found_p)
32612 {
32613 face = face->ascii_face;
32614 font = face->font;
32615 }
32616 boff = font->baseline_offset;
32617 if (font->vertical_centering)
32618 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32619 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32620 font_ascent += boff;
32621 font_descent -= boff;
32622 font_height = font_ascent + font_descent;
32623
32624 cmp->font = font;
32625
32626 pcm = NULL;
32627 if (! font_not_found_p)
32628 {
32629 get_char_face_and_encoding (it->f, c, it->face_id,
32630 &char2b, false);
32631 pcm = get_per_char_metric (font, &char2b);
32632 }
32633
32634
32635 if (pcm)
32636 {
32637 width = cmp->glyph_len > 0 ? pcm->width : 0;
32638 ascent = pcm->ascent;
32639 descent = pcm->descent;
32640 lbearing = pcm->lbearing;
32641 rbearing = pcm->rbearing;
32642 }
32643 else
32644 {
32645 width = cmp->glyph_len > 0 ? font->space_width : 0;
32646 ascent = FONT_BASE (font);
32647 descent = FONT_DESCENT (font);
32648 lbearing = 0;
32649 rbearing = width;
32650 }
32651
32652 rightmost = width;
32653 leftmost = 0;
32654 lowest = - descent + boff;
32655 highest = ascent + boff;
32656
32657 if (! font_not_found_p
32658 && font->default_ascent
32659 && CHAR_TABLE_P (Vuse_default_ascent)
32660 && !NILP (Faref (Vuse_default_ascent,
32661 make_fixnum (it->char_to_display))))
32662 highest = font->default_ascent + boff;
32663
32664
32665
32666
32667 cmp->offsets[i * 2] = 0;
32668 cmp->offsets[i * 2 + 1] = boff;
32669 cmp->lbearing = lbearing;
32670 cmp->rbearing = rbearing;
32671
32672
32673 for (i++; i < glyph_len; i++)
32674 {
32675 int left, right, btm, top;
32676 int ch = COMPOSITION_GLYPH (cmp, i);
32677 int face_id;
32678 struct face *this_face;
32679
32680 if (ch == '\t')
32681 ch = ' ';
32682 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32683 this_face = FACE_FROM_ID (it->f, face_id);
32684 font = this_face->font;
32685
32686 if (font == NULL)
32687 pcm = NULL;
32688 else
32689 {
32690 get_char_face_and_encoding (it->f, ch, face_id,
32691 &char2b, false);
32692 pcm = get_per_char_metric (font, &char2b);
32693 }
32694 if (! pcm)
32695 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32696 else
32697 {
32698 width = pcm->width;
32699 ascent = pcm->ascent;
32700 descent = pcm->descent;
32701 lbearing = pcm->lbearing;
32702 rbearing = pcm->rbearing;
32703 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32704 {
32705
32706
32707 left = (leftmost + rightmost - width) / 2;
32708 btm = - descent + boff;
32709 if (font->relative_compose
32710 && (! CHAR_TABLE_P (Vignore_relative_composition)
32711 || NILP (Faref (Vignore_relative_composition,
32712 make_fixnum (ch)))))
32713 {
32714
32715 if (- descent >= font->relative_compose)
32716
32717 btm = highest + 1;
32718 else if (ascent <= 0)
32719
32720 btm = lowest - 1 - ascent - descent;
32721 }
32722 }
32723 else
32724 {
32725
32726
32727
32728
32729
32730
32731
32732
32733
32734
32735
32736
32737
32738
32739
32740 int rule = COMPOSITION_RULE (cmp, i);
32741 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32742
32743 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32744 grefx = gref % 3, nrefx = nref % 3;
32745 grefy = gref / 3, nrefy = nref / 3;
32746 if (xoff)
32747 xoff = font_height * (xoff - 128) / 256;
32748 if (yoff)
32749 yoff = font_height * (yoff - 128) / 256;
32750
32751 left = (leftmost
32752 + grefx * (rightmost - leftmost) / 2
32753 - nrefx * width / 2
32754 + xoff);
32755
32756 btm = ((grefy == 0 ? highest
32757 : grefy == 1 ? 0
32758 : grefy == 2 ? lowest
32759 : (highest + lowest) / 2)
32760 - (nrefy == 0 ? ascent + descent
32761 : nrefy == 1 ? descent - boff
32762 : nrefy == 2 ? 0
32763 : (ascent + descent) / 2)
32764 + yoff);
32765 }
32766
32767 cmp->offsets[i * 2] = left;
32768 cmp->offsets[i * 2 + 1] = btm + descent;
32769
32770
32771 if (width > 0)
32772 {
32773 right = left + width;
32774 if (left < leftmost)
32775 leftmost = left;
32776 if (right > rightmost)
32777 rightmost = right;
32778 }
32779 top = btm + descent + ascent;
32780 if (top > highest)
32781 highest = top;
32782 if (btm < lowest)
32783 lowest = btm;
32784
32785 if (cmp->lbearing > left + lbearing)
32786 cmp->lbearing = left + lbearing;
32787 if (cmp->rbearing < left + rbearing)
32788 cmp->rbearing = left + rbearing;
32789 }
32790 }
32791
32792
32793
32794
32795 if (leftmost < 0)
32796 {
32797 for (i = 0; i < cmp->glyph_len; i++)
32798 cmp->offsets[i * 2] -= leftmost;
32799 rightmost -= leftmost;
32800 cmp->lbearing -= leftmost;
32801 cmp->rbearing -= leftmost;
32802 }
32803
32804 if (left_padded && cmp->lbearing < 0)
32805 {
32806 for (i = 0; i < cmp->glyph_len; i++)
32807 cmp->offsets[i * 2] -= cmp->lbearing;
32808 rightmost -= cmp->lbearing;
32809 cmp->rbearing -= cmp->lbearing;
32810 cmp->lbearing = 0;
32811 }
32812 if (right_padded && rightmost < cmp->rbearing)
32813 {
32814 rightmost = cmp->rbearing;
32815 }
32816
32817 cmp->pixel_width = rightmost;
32818 cmp->ascent = highest;
32819 cmp->descent = - lowest;
32820 if (cmp->ascent < font_ascent)
32821 cmp->ascent = font_ascent;
32822 if (cmp->descent < font_descent)
32823 cmp->descent = font_descent;
32824 }
32825
32826 if (it->glyph_row
32827 && (cmp->lbearing < 0
32828 || cmp->rbearing > cmp->pixel_width))
32829 it->glyph_row->contains_overlapping_glyphs_p = true;
32830
32831 it->pixel_width = cmp->pixel_width;
32832 it->ascent = it->phys_ascent = cmp->ascent;
32833 it->descent = it->phys_descent = cmp->descent;
32834 IT_APPLY_FACE_BOX(it, face);
32835
32836
32837
32838 if (face->overline_p)
32839 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32840
32841 take_vertical_position_into_account (it);
32842 if (it->ascent < 0)
32843 it->ascent = 0;
32844 if (it->descent < 0)
32845 it->descent = 0;
32846
32847 if (it->glyph_row && cmp->glyph_len > 0)
32848 append_composite_glyph (it);
32849 }
32850 else if (it->what == IT_COMPOSITION)
32851 {
32852
32853 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32854 Lisp_Object gstring;
32855 struct font_metrics metrics;
32856
32857 it->nglyphs = 1;
32858
32859 gstring = composition_gstring_from_id (it->cmp_it.id);
32860 it->pixel_width
32861 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32862 &metrics);
32863 if (it->pixel_width == 0)
32864 {
32865 it->glyph_not_available_p = true;
32866 it->phys_ascent = it->ascent;
32867 it->phys_descent = it->descent;
32868 it->pixel_width = face->font->space_width;
32869 }
32870 else
32871 {
32872 if (it->glyph_row
32873 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32874 it->glyph_row->contains_overlapping_glyphs_p = true;
32875 it->ascent = it->phys_ascent = metrics.ascent;
32876 it->descent = it->phys_descent = metrics.descent;
32877 }
32878 IT_APPLY_FACE_BOX(it, face);
32879
32880
32881
32882 if (face->overline_p)
32883 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32884 take_vertical_position_into_account (it);
32885 if (it->ascent < 0)
32886 it->ascent = 0;
32887 if (it->descent < 0)
32888 it->descent = 0;
32889
32890 if (it->glyph_row)
32891 append_composite_glyph (it);
32892 }
32893 else if (it->what == IT_GLYPHLESS)
32894 produce_glyphless_glyph (it, false, Qnil);
32895 else if (it->what == IT_IMAGE)
32896 produce_image_glyph (it);
32897 else if (it->what == IT_STRETCH)
32898 produce_stretch_glyph (it);
32899 else if (it->what == IT_XWIDGET)
32900 produce_xwidget_glyph (it);
32901
32902 done:
32903
32904
32905 eassert (it->ascent >= 0 && it->descent >= 0);
32906 if (it->area == TEXT_AREA)
32907 it->current_x += it->pixel_width;
32908
32909 if (extra_line_spacing > 0)
32910 {
32911 it->descent += extra_line_spacing;
32912 if (extra_line_spacing > it->max_extra_line_spacing)
32913 it->max_extra_line_spacing = extra_line_spacing;
32914 }
32915
32916 it->max_ascent = max (it->max_ascent, it->ascent);
32917 it->max_descent = max (it->max_descent, it->descent);
32918 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32919 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32920 }
32921
32922
32923
32924
32925
32926
32927 void
32928 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32929 struct glyph *start, enum glyph_row_area updated_area, int len)
32930 {
32931 int x, hpos, chpos = w->phys_cursor.hpos;
32932
32933 eassert (updated_row);
32934
32935
32936
32937 if (!updated_row->reversed_p && chpos < 0)
32938 chpos = 0;
32939 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32940 chpos = updated_row->used[TEXT_AREA] - 1;
32941
32942 block_input ();
32943
32944
32945
32946 hpos = start - updated_row->glyphs[updated_area];
32947 x = draw_glyphs (w, w->output_cursor.x,
32948 updated_row, updated_area,
32949 hpos, hpos + len,
32950 DRAW_NORMAL_TEXT, 0);
32951
32952
32953 if (updated_area == TEXT_AREA
32954 && w->phys_cursor_on_p
32955 && w->phys_cursor.vpos == w->output_cursor.vpos
32956 && chpos >= hpos
32957 && chpos < hpos + len)
32958 w->phys_cursor_on_p = false;
32959
32960 unblock_input ();
32961
32962
32963 w->output_cursor.hpos += len;
32964 w->output_cursor.x = x;
32965 }
32966
32967
32968
32969
32970
32971 void
32972 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
32973 struct glyph *start, enum glyph_row_area updated_area, int len)
32974 {
32975 struct frame *f;
32976 int line_height, shift_by_width, shifted_region_width;
32977 struct glyph_row *row;
32978 struct glyph *glyph;
32979 int frame_x, frame_y;
32980 ptrdiff_t hpos;
32981
32982 eassert (updated_row);
32983 block_input ();
32984 f = XFRAME (WINDOW_FRAME (w));
32985
32986
32987 row = updated_row;
32988 line_height = row->height;
32989
32990
32991 shift_by_width = 0;
32992 for (glyph = start; glyph < start + len; ++glyph)
32993 shift_by_width += glyph->pixel_width;
32994
32995
32996 shifted_region_width = (window_box_width (w, updated_area)
32997 - w->output_cursor.x
32998 - shift_by_width);
32999
33000
33001 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
33002 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
33003
33004 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
33005 line_height, shift_by_width);
33006
33007
33008 hpos = start - row->glyphs[updated_area];
33009 draw_glyphs (w, w->output_cursor.x, row, updated_area,
33010 hpos, hpos + len,
33011 DRAW_NORMAL_TEXT, 0);
33012
33013
33014 w->output_cursor.hpos += len;
33015 w->output_cursor.x += shift_by_width;
33016 unblock_input ();
33017 }
33018
33019
33020
33021
33022
33023
33024
33025
33026
33027
33028 void
33029 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
33030 enum glyph_row_area updated_area, int to_x)
33031 {
33032 struct frame *f;
33033 int max_x, min_y, max_y;
33034 int from_x, from_y, to_y;
33035 struct face *face;
33036
33037 eassert (updated_row);
33038 f = XFRAME (w->frame);
33039 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
33040
33041 if (updated_row->full_width_p)
33042 max_x = (WINDOW_PIXEL_WIDTH (w)
33043 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
33044 else
33045 max_x = window_box_width (w, updated_area);
33046 max_y = window_text_bottom_y (w);
33047
33048
33049
33050 if (to_x == 0)
33051 return;
33052 else if (to_x < 0)
33053 to_x = max_x;
33054 else
33055 to_x = min (to_x, max_x);
33056
33057 to_y = min (max_y, w->output_cursor.y + updated_row->height);
33058
33059
33060 if (!updated_row->full_width_p)
33061 notice_overwritten_cursor (w, updated_area,
33062 w->output_cursor.x, -1,
33063 updated_row->y,
33064 MATRIX_ROW_BOTTOM_Y (updated_row));
33065
33066 from_x = w->output_cursor.x;
33067
33068
33069 if (updated_row->full_width_p)
33070 {
33071 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
33072 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
33073 }
33074 else
33075 {
33076 int area_left = window_box_left (w, updated_area);
33077 from_x += area_left;
33078 to_x += area_left;
33079 }
33080
33081 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
33082 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
33083 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
33084
33085
33086 if (to_x > from_x && to_y > from_y)
33087 {
33088 block_input ();
33089 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
33090 to_x - from_x, to_y - from_y);
33091
33092 if (face && !updated_row->stipple_p)
33093 updated_row->stipple_p = face->stipple;
33094 unblock_input ();
33095 }
33096 }
33097
33098 #endif
33099
33100
33101
33102
33103
33104
33105
33106
33107
33108
33109
33110 static enum text_cursor_kinds
33111 get_specified_cursor_type (Lisp_Object arg, int *width)
33112 {
33113 enum text_cursor_kinds type;
33114
33115 if (NILP (arg))
33116 return NO_CURSOR;
33117
33118 if (EQ (arg, Qbox))
33119 return FILLED_BOX_CURSOR;
33120
33121 if (EQ (arg, Qhollow))
33122 return HOLLOW_BOX_CURSOR;
33123
33124 if (EQ (arg, Qbar))
33125 {
33126 *width = 2;
33127 return BAR_CURSOR;
33128 }
33129
33130 if (EQ (arg, Qhbar))
33131 {
33132 *width = 2;
33133 return HBAR_CURSOR;
33134 }
33135
33136 if (CONSP (arg)
33137 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
33138 {
33139 *width = XFIXNUM (XCDR (arg));
33140
33141 if (EQ (XCAR (arg), Qbox))
33142 return FILLED_BOX_CURSOR;
33143 else if (EQ (XCAR (arg), Qbar))
33144 return BAR_CURSOR;
33145 else if (EQ (XCAR (arg), Qhbar))
33146 return HBAR_CURSOR;
33147 }
33148
33149
33150
33151
33152 type = HOLLOW_BOX_CURSOR;
33153
33154 return type;
33155 }
33156
33157
33158 void
33159 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
33160 {
33161 int width = 1;
33162 Lisp_Object tem;
33163
33164 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
33165 FRAME_CURSOR_WIDTH (f) = width;
33166
33167
33168
33169 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
33170 if (!NILP (tem))
33171 {
33172 FRAME_BLINK_OFF_CURSOR (f)
33173 = get_specified_cursor_type (XCDR (tem), &width);
33174 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
33175 }
33176 else
33177 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
33178
33179
33180 f->cursor_type_changed = true;
33181 }
33182
33183
33184 #ifdef HAVE_WINDOW_SYSTEM
33185
33186
33187
33188
33189
33190
33191
33192
33193
33194
33195
33196
33197 static enum text_cursor_kinds
33198 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
33199 bool *active_cursor)
33200 {
33201 struct frame *f = XFRAME (w->frame);
33202 struct buffer *b = XBUFFER (w->contents);
33203 int cursor_type = DEFAULT_CURSOR;
33204 Lisp_Object alt_cursor;
33205 bool non_selected = false;
33206
33207 *active_cursor = true;
33208
33209
33210 if (cursor_in_echo_area
33211 && FRAME_HAS_MINIBUF_P (f)
33212 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
33213 {
33214 if (w == XWINDOW (echo_area_window))
33215 {
33216 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
33217 {
33218 *width = FRAME_CURSOR_WIDTH (f);
33219 return FRAME_DESIRED_CURSOR (f);
33220 }
33221 else
33222 return get_specified_cursor_type (BVAR (b, cursor_type), width);
33223 }
33224
33225 *active_cursor = false;
33226 non_selected = true;
33227 }
33228
33229
33230 else if (w != XWINDOW (f->selected_window)
33231 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
33232 {
33233 *active_cursor = false;
33234
33235 if (MINI_WINDOW_P (w) &&
33236 (minibuf_level == 0
33237 || is_minibuffer (0, w->contents)))
33238 return NO_CURSOR;
33239
33240 non_selected = true;
33241 }
33242
33243
33244 if (NILP (BVAR (b, cursor_type)))
33245 return NO_CURSOR;
33246
33247
33248 if (EQ (BVAR (b, cursor_type), Qt))
33249 {
33250 cursor_type = FRAME_DESIRED_CURSOR (f);
33251 *width = FRAME_CURSOR_WIDTH (f);
33252 }
33253 else
33254 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33255
33256
33257
33258 if (non_selected)
33259 {
33260 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33261 if (!EQ (Qt, alt_cursor))
33262 return get_specified_cursor_type (alt_cursor, width);
33263
33264 if (cursor_type == FILLED_BOX_CURSOR)
33265 cursor_type = HOLLOW_BOX_CURSOR;
33266 else if (cursor_type == BAR_CURSOR && *width > 1)
33267 --*width;
33268 return cursor_type;
33269 }
33270
33271
33272 if (!w->cursor_off_p)
33273 {
33274 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33275 return NO_CURSOR;
33276 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33277 {
33278 if (cursor_type == FILLED_BOX_CURSOR)
33279 {
33280
33281
33282
33283
33284 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33285 if (img != NULL && IMAGEP (img->spec))
33286 {
33287
33288
33289
33290
33291
33292
33293 if (!img->mask
33294 || (CONSP (BVAR (b, cursor_type))
33295 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33296 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33297 cursor_type = HOLLOW_BOX_CURSOR;
33298 }
33299 }
33300 else if (cursor_type != NO_CURSOR)
33301 {
33302
33303
33304
33305 cursor_type = HOLLOW_BOX_CURSOR;
33306 }
33307 }
33308 return cursor_type;
33309 }
33310
33311
33312
33313
33314 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33315 return get_specified_cursor_type (XCDR (alt_cursor), width);
33316
33317
33318 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33319 {
33320 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33321 return FRAME_BLINK_OFF_CURSOR (f);
33322 }
33323
33324 #if false
33325
33326
33327
33328
33329
33330
33331
33332
33333
33334
33335 if (cursor_type == FILLED_BOX_CURSOR)
33336 return HOLLOW_BOX_CURSOR;
33337
33338 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33339 {
33340 *width = 1;
33341 return cursor_type;
33342 }
33343 #endif
33344
33345 return NO_CURSOR;
33346 }
33347
33348
33349
33350
33351
33352
33353
33354
33355
33356 static void
33357 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33358 int x0, int x1, int y0, int y1)
33359 {
33360 int cx0, cx1, cy0, cy1;
33361 struct glyph_row *row;
33362
33363 if (!w->phys_cursor_on_p)
33364 return;
33365 if (area != TEXT_AREA)
33366 return;
33367
33368 if (w->phys_cursor.vpos < 0
33369 || w->phys_cursor.vpos >= w->current_matrix->nrows
33370 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33371 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33372 return;
33373
33374 if (row->cursor_in_fringe_p)
33375 {
33376 row->cursor_in_fringe_p = false;
33377 draw_fringe_bitmap (w, row, row->reversed_p);
33378 w->phys_cursor_on_p = false;
33379 return;
33380 }
33381
33382 cx0 = w->phys_cursor.x;
33383 cx1 = cx0 + w->phys_cursor_width;
33384 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33385 return;
33386
33387
33388
33389
33390
33391
33392
33393
33394
33395
33396
33397
33398
33399
33400
33401
33402
33403 cy0 = w->phys_cursor.y;
33404 cy1 = cy0 + w->phys_cursor_height;
33405 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33406 return;
33407
33408 w->phys_cursor_on_p = false;
33409 }
33410
33411 #endif
33412
33413
33414
33415
33416
33417
33418 #ifdef HAVE_WINDOW_SYSTEM
33419
33420
33421
33422
33423
33424 void
33425 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33426 enum glyph_row_area area, int overlaps)
33427 {
33428 int i, x;
33429
33430 block_input ();
33431
33432 x = 0;
33433 for (i = 0; i < row->used[area];)
33434 {
33435 if (row->glyphs[area][i].overlaps_vertically_p)
33436 {
33437 int start = i, start_x = x;
33438
33439 do
33440 {
33441 x += row->glyphs[area][i].pixel_width;
33442 ++i;
33443 }
33444 while (i < row->used[area]
33445 && row->glyphs[area][i].overlaps_vertically_p);
33446
33447 draw_glyphs (w, start_x, row, area,
33448 start, i,
33449 DRAW_NORMAL_TEXT, overlaps);
33450 }
33451 else
33452 {
33453 x += row->glyphs[area][i].pixel_width;
33454 ++i;
33455 }
33456 }
33457
33458 unblock_input ();
33459 }
33460
33461
33462
33463
33464
33465
33466 void
33467 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33468 enum draw_glyphs_face hl)
33469 {
33470
33471
33472
33473 if ((row->reversed_p
33474 ? (w->phys_cursor.hpos >= 0)
33475 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33476 {
33477 bool on_p = w->phys_cursor_on_p;
33478 int x1;
33479 int hpos = w->phys_cursor.hpos;
33480
33481
33482
33483
33484 if (!row->reversed_p && hpos < 0)
33485 hpos = 0;
33486 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33487 hpos = row->used[TEXT_AREA] - 1;
33488
33489 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33490 hl, 0);
33491 w->phys_cursor_on_p = on_p;
33492
33493 if (hl == DRAW_CURSOR)
33494 w->phys_cursor_width = x1 - w->phys_cursor.x;
33495
33496
33497
33498 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33499 {
33500 w->phys_cursor_width = x1 - w->phys_cursor.x;
33501
33502 if (row > w->current_matrix->rows
33503 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33504 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33505 OVERLAPS_ERASED_CURSOR);
33506
33507 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33508 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33509 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33510 OVERLAPS_ERASED_CURSOR);
33511 }
33512 }
33513 }
33514
33515
33516
33517
33518 void
33519 erase_phys_cursor (struct window *w)
33520 {
33521 struct frame *f = XFRAME (w->frame);
33522 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33523 int hpos = w->phys_cursor.hpos;
33524 int vpos = w->phys_cursor.vpos;
33525 bool mouse_face_here_p = false;
33526 struct glyph_matrix *active_glyphs = w->current_matrix;
33527 struct glyph_row *cursor_row;
33528 struct glyph *cursor_glyph;
33529 enum draw_glyphs_face hl;
33530
33531
33532
33533 if (w->phys_cursor_type == NO_CURSOR)
33534 goto mark_cursor_off;
33535
33536
33537
33538 if (vpos >= active_glyphs->nrows)
33539 goto mark_cursor_off;
33540
33541
33542
33543 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33544 if (!cursor_row->enabled_p)
33545 goto mark_cursor_off;
33546
33547
33548
33549 cursor_row->visible_height = min (cursor_row->visible_height,
33550 window_text_bottom_y (w) - cursor_row->y);
33551
33552
33553
33554
33555 if (cursor_row->visible_height <= 0)
33556 goto mark_cursor_off;
33557
33558
33559 if (cursor_row->cursor_in_fringe_p)
33560 {
33561 cursor_row->cursor_in_fringe_p = false;
33562 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33563 goto mark_cursor_off;
33564 }
33565
33566
33567
33568
33569
33570
33571 if ((cursor_row->reversed_p
33572 ? (w->phys_cursor.hpos < 0)
33573 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33574 goto mark_cursor_off;
33575
33576
33577
33578
33579 if (!cursor_row->reversed_p && hpos < 0)
33580 hpos = 0;
33581 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33582 hpos = cursor_row->used[TEXT_AREA] - 1;
33583
33584
33585
33586 if (! NILP (hlinfo->mouse_face_window)
33587 && coords_in_mouse_face_p (w, hpos, vpos)
33588
33589
33590
33591 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33592 mouse_face_here_p = true;
33593
33594 #ifdef HAVE_WINDOW_SYSTEM
33595
33596
33597
33598
33599 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33600 {
33601 w->phys_cursor_on_p = false;
33602 w->phys_cursor_type = NO_CURSOR;
33603 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33604 return;
33605 }
33606 #endif
33607
33608
33609 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33610 {
33611 int x, y;
33612 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33613 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33614 int width;
33615
33616 cursor_glyph = get_phys_cursor_glyph (w);
33617 if (cursor_glyph == NULL)
33618 goto mark_cursor_off;
33619
33620 width = cursor_glyph->pixel_width;
33621 x = w->phys_cursor.x;
33622 if (x < 0)
33623 {
33624 width += x;
33625 x = 0;
33626 }
33627 width = min (width, window_box_width (w, TEXT_AREA) - x);
33628 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33629 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33630
33631 if (width > 0)
33632 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33633 }
33634
33635
33636 if (mouse_face_here_p)
33637 hl = DRAW_MOUSE_FACE;
33638 else
33639 hl = DRAW_NORMAL_TEXT;
33640 draw_phys_cursor_glyph (w, cursor_row, hl);
33641
33642 mark_cursor_off:
33643 w->phys_cursor_on_p = false;
33644 w->phys_cursor_type = NO_CURSOR;
33645 }
33646
33647
33648
33649
33650
33651
33652 void
33653 display_and_set_cursor (struct window *w, bool on,
33654 int hpos, int vpos, int x, int y)
33655 {
33656 struct frame *f = XFRAME (w->frame);
33657 int new_cursor_type;
33658 int new_cursor_width UNINIT;
33659 bool active_cursor;
33660 struct glyph_row *glyph_row;
33661 struct glyph *glyph;
33662
33663
33664
33665
33666
33667 if (! FRAME_REDISPLAY_P (f)
33668 || vpos >= w->current_matrix->nrows
33669 || hpos >= w->current_matrix->matrix_w)
33670 return;
33671
33672
33673 if (!on && !w->phys_cursor_on_p)
33674 return;
33675
33676 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33677
33678
33679 if (!glyph_row->enabled_p)
33680 {
33681 w->phys_cursor_on_p = false;
33682 return;
33683 }
33684
33685
33686
33687
33688
33689
33690
33691
33692
33693 if (FRAME_GARBAGED_P (f))
33694 {
33695 if (on)
33696 {
33697 w->phys_cursor.x = x;
33698 w->phys_cursor.y = glyph_row->y;
33699 w->phys_cursor.hpos = hpos;
33700 w->phys_cursor.vpos = vpos;
33701 }
33702 return;
33703 }
33704
33705 glyph = NULL;
33706 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33707 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33708
33709 eassert (input_blocked_p ());
33710
33711
33712 new_cursor_type = get_window_cursor_type (w, glyph,
33713 &new_cursor_width, &active_cursor);
33714
33715
33716
33717
33718 if (w->phys_cursor_on_p
33719 && (!on
33720 || w->phys_cursor.x != x
33721 || w->phys_cursor.y != y
33722
33723
33724
33725 || hpos < 0
33726 || new_cursor_type != w->phys_cursor_type
33727 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33728 && new_cursor_width != w->phys_cursor_width)))
33729 erase_phys_cursor (w);
33730
33731
33732
33733
33734
33735
33736 if (on)
33737 {
33738 w->phys_cursor_ascent = glyph_row->ascent;
33739 w->phys_cursor_height = glyph_row->height;
33740
33741
33742
33743 w->phys_cursor.x = x;
33744 w->phys_cursor.y = glyph_row->y;
33745 w->phys_cursor.hpos = hpos;
33746 w->phys_cursor.vpos = vpos;
33747 }
33748
33749 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33750 new_cursor_type, new_cursor_width,
33751 on, active_cursor);
33752 }
33753
33754
33755
33756
33757
33758 static void
33759 update_window_cursor (struct window *w, bool on)
33760 {
33761
33762
33763 if (w->current_matrix)
33764 {
33765 int hpos = w->phys_cursor.hpos;
33766 int vpos = w->phys_cursor.vpos;
33767 struct glyph_row *row;
33768
33769 if (vpos >= w->current_matrix->nrows
33770 || hpos >= w->current_matrix->matrix_w)
33771 return;
33772
33773 row = MATRIX_ROW (w->current_matrix, vpos);
33774
33775
33776
33777
33778 if (!row->reversed_p && hpos < 0)
33779 hpos = 0;
33780 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33781 hpos = row->used[TEXT_AREA] - 1;
33782
33783 block_input ();
33784 display_and_set_cursor (w, on, hpos, vpos,
33785 w->phys_cursor.x, w->phys_cursor.y);
33786 unblock_input ();
33787 }
33788 }
33789
33790
33791
33792
33793
33794 static void
33795 update_cursor_in_window_tree (struct window *w, bool on_p)
33796 {
33797 while (w)
33798 {
33799 if (WINDOWP (w->contents))
33800 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33801 else
33802 update_window_cursor (w, on_p);
33803
33804 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33805 }
33806 }
33807
33808
33809
33810
33811
33812
33813 void
33814 gui_update_cursor (struct frame *f, bool on_p)
33815 {
33816 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33817 }
33818
33819
33820
33821
33822
33823
33824
33825 void
33826 gui_clear_cursor (struct window *w)
33827 {
33828 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33829 update_window_cursor (w, false);
33830 }
33831
33832 #endif
33833
33834
33835
33836 static void
33837 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33838 int start_hpos, int end_hpos,
33839 enum draw_glyphs_face draw)
33840 {
33841 #ifdef HAVE_WINDOW_SYSTEM
33842 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33843 {
33844 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33845 return;
33846 }
33847 #endif
33848
33849 #ifndef HAVE_ANDROID
33850 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33851 #endif
33852 }
33853
33854
33855
33856 static void
33857 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33858 {
33859
33860
33861 if (!WINDOWP (hlinfo->mouse_face_window))
33862 return;
33863
33864 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33865 struct frame *f = XFRAME (WINDOW_FRAME (w));
33866
33867
33868 if (f != hlinfo->mouse_face_mouse_frame)
33869 return;
33870
33871 if (
33872
33873 w->current_matrix != NULL
33874
33875 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33876
33877
33878 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33879 {
33880 bool phys_cursor_on_p = w->phys_cursor_on_p;
33881 #ifdef HAVE_WINDOW_SYSTEM
33882 int mouse_off = 0;
33883 #endif
33884 struct glyph_row *row, *first, *last;
33885
33886 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33887 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33888
33889 for (row = first; row <= last && row->enabled_p; ++row)
33890 {
33891 int start_hpos, end_hpos, start_x;
33892
33893
33894 if (row == first)
33895 {
33896
33897
33898
33899
33900 if (!row->reversed_p)
33901 {
33902 start_hpos = hlinfo->mouse_face_beg_col;
33903 start_x = hlinfo->mouse_face_beg_x;
33904 }
33905 else if (row == last)
33906 {
33907 start_hpos = hlinfo->mouse_face_end_col;
33908 start_x = hlinfo->mouse_face_end_x;
33909 }
33910 else
33911 {
33912 start_hpos = 0;
33913 start_x = 0;
33914 }
33915 }
33916 else if (row->reversed_p && row == last)
33917 {
33918 start_hpos = hlinfo->mouse_face_end_col;
33919 start_x = hlinfo->mouse_face_end_x;
33920 }
33921 else
33922 {
33923 start_hpos = 0;
33924 start_x = 0;
33925 }
33926
33927 if (row == last)
33928 {
33929 if (!row->reversed_p)
33930 end_hpos = hlinfo->mouse_face_end_col;
33931 else if (row == first)
33932 end_hpos = hlinfo->mouse_face_beg_col;
33933 else
33934 {
33935 end_hpos = row->used[TEXT_AREA];
33936 if (draw == DRAW_NORMAL_TEXT)
33937 row->fill_line_p = true;
33938 }
33939 }
33940 else if (row->reversed_p && row == first)
33941 end_hpos = hlinfo->mouse_face_beg_col;
33942 else
33943 {
33944 end_hpos = row->used[TEXT_AREA];
33945 if (draw == DRAW_NORMAL_TEXT)
33946 row->fill_line_p = true;
33947 }
33948
33949 if (end_hpos > start_hpos)
33950 {
33951 draw_row_with_mouse_face (w, start_x, row,
33952 start_hpos, end_hpos, draw);
33953
33954 row->mouse_face_p
33955 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33956 }
33957 #ifdef HAVE_WINDOW_SYSTEM
33958
33959 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33960
33961
33962 && !w->pseudo_window_p
33963 && draw == DRAW_MOUSE_FACE)
33964 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
33965 #endif
33966 }
33967
33968
33969
33970 if (FRAME_WINDOW_P (f)
33971 && phys_cursor_on_p && !w->phys_cursor_on_p)
33972 {
33973 #ifdef HAVE_WINDOW_SYSTEM
33974 int hpos = w->phys_cursor.hpos;
33975 int old_phys_cursor_x = w->phys_cursor.x;
33976
33977
33978
33979
33980 if (!row->reversed_p && hpos < 0)
33981 hpos = 0;
33982 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33983 hpos = row->used[TEXT_AREA] - 1;
33984
33985 block_input ();
33986 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
33987 w->phys_cursor.x + mouse_off,
33988 w->phys_cursor.y);
33989
33990
33991 w->phys_cursor.x = old_phys_cursor_x;
33992 unblock_input ();
33993 #endif
33994 }
33995 }
33996
33997 #ifdef HAVE_WINDOW_SYSTEM
33998
33999 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
34000 {
34001 if (draw == DRAW_NORMAL_TEXT
34002 #ifndef HAVE_EXT_TOOL_BAR
34003 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
34004 #endif
34005 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
34006 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
34007 else
34008 if (draw == DRAW_MOUSE_FACE)
34009 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
34010 else
34011 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
34012 }
34013 #endif
34014 }
34015
34016
34017
34018
34019
34020
34021 bool
34022 clear_mouse_face (Mouse_HLInfo *hlinfo)
34023 {
34024 bool cleared
34025 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
34026 if (cleared)
34027 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
34028 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
34029 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
34030 hlinfo->mouse_face_window = Qnil;
34031 hlinfo->mouse_face_overlay = Qnil;
34032 return cleared;
34033 }
34034
34035
34036
34037 static bool
34038 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
34039 {
34040 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
34041
34042
34043 if (!(WINDOWP (hlinfo->mouse_face_window)
34044 && XWINDOW (hlinfo->mouse_face_window) == w))
34045 return false;
34046 if (vpos < hlinfo->mouse_face_beg_row
34047 || vpos > hlinfo->mouse_face_end_row)
34048 return false;
34049 if (vpos > hlinfo->mouse_face_beg_row
34050 && vpos < hlinfo->mouse_face_end_row)
34051 return true;
34052
34053 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
34054 {
34055 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34056 {
34057 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
34058 return true;
34059 }
34060 else if ((vpos == hlinfo->mouse_face_beg_row
34061 && hpos >= hlinfo->mouse_face_beg_col)
34062 || (vpos == hlinfo->mouse_face_end_row
34063 && hpos < hlinfo->mouse_face_end_col))
34064 return true;
34065 }
34066 else
34067 {
34068 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34069 {
34070 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
34071 return true;
34072 }
34073 else if ((vpos == hlinfo->mouse_face_beg_row
34074 && hpos <= hlinfo->mouse_face_beg_col)
34075 || (vpos == hlinfo->mouse_face_end_row
34076 && hpos > hlinfo->mouse_face_end_col))
34077 return true;
34078 }
34079 return false;
34080 }
34081
34082
34083
34084
34085
34086 bool
34087 cursor_in_mouse_face_p (struct window *w)
34088 {
34089 int vpos = w->phys_cursor.vpos;
34090
34091
34092
34093 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
34094 return false;
34095
34096 int hpos = w->phys_cursor.hpos;
34097 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
34098
34099
34100
34101
34102 if (!row->reversed_p && hpos < 0)
34103 hpos = 0;
34104 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34105 hpos = row->used[TEXT_AREA] - 1;
34106
34107 return coords_in_mouse_face_p (w, hpos, vpos);
34108 }
34109
34110
34111
34112
34113
34114
34115
34116
34117
34118 static void
34119 rows_from_pos_range (struct window *w,
34120 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
34121 Lisp_Object disp_string,
34122 struct glyph_row **start, struct glyph_row **end)
34123 {
34124 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34125 int last_y = window_text_bottom_y (w);
34126 struct glyph_row *row;
34127
34128 *start = NULL;
34129 *end = NULL;
34130
34131 while (!first->enabled_p
34132 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
34133 first++;
34134
34135
34136 for (row = first;
34137 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
34138 row++)
34139 {
34140
34141
34142
34143 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
34144 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
34145
34146
34147
34148
34149 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
34150 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
34151 && !row->ends_at_zv_p
34152 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
34153 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
34154 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
34155 && !row->ends_at_zv_p
34156 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
34157 {
34158
34159
34160
34161
34162
34163
34164
34165
34166
34167
34168 struct glyph *g = row->glyphs[TEXT_AREA];
34169 struct glyph *e = g + row->used[TEXT_AREA];
34170
34171 while (g < e)
34172 {
34173 if (((BUFFERP (g->object) || NILP (g->object))
34174 && start_charpos <= g->charpos && g->charpos < end_charpos)
34175
34176
34177 || EQ (g->object, disp_string))
34178 *start = row;
34179 g++;
34180 }
34181 if (*start)
34182 break;
34183 }
34184 }
34185
34186
34187 if (!*start
34188
34189
34190 && !(row->enabled_p
34191 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
34192 row = first;
34193 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
34194 {
34195 struct glyph_row *next = row + 1;
34196 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
34197
34198 if (!next->enabled_p
34199 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
34200
34201
34202
34203 || (start_charpos < next_start
34204 && end_charpos < next_start)
34205 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
34206 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
34207 && !next->ends_at_zv_p
34208 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
34209 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
34210 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
34211 && !next->ends_at_zv_p
34212 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
34213 {
34214 *end = row;
34215 break;
34216 }
34217 else
34218 {
34219
34220
34221
34222 struct glyph *g = next->glyphs[TEXT_AREA];
34223 struct glyph *s = g;
34224 struct glyph *e = g + next->used[TEXT_AREA];
34225
34226 while (g < e)
34227 {
34228 if (((BUFFERP (g->object) || NILP (g->object))
34229 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
34230
34231
34232
34233
34234
34235 || (((!next->reversed_p && g == s)
34236 || (next->reversed_p && g == e - 1))
34237 && (g->charpos == end_charpos
34238
34239
34240 || (g->charpos == -1
34241 && !row->ends_at_zv_p
34242 && next_start == end_charpos)))))
34243
34244
34245 || EQ (g->object, disp_string))
34246 break;
34247 g++;
34248 }
34249 if (g == e)
34250 {
34251 *end = row;
34252 break;
34253 }
34254
34255
34256 else if (next->ends_at_zv_p)
34257 {
34258 *end = next;
34259 break;
34260 }
34261 }
34262 }
34263 }
34264
34265
34266
34267
34268
34269
34270
34271
34272
34273
34274 static void
34275 mouse_face_from_buffer_pos (Lisp_Object window,
34276 Mouse_HLInfo *hlinfo,
34277 ptrdiff_t mouse_charpos,
34278 ptrdiff_t start_charpos,
34279 ptrdiff_t end_charpos,
34280 Lisp_Object before_string,
34281 Lisp_Object after_string,
34282 Lisp_Object disp_string)
34283 {
34284 struct window *w = XWINDOW (window);
34285 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34286 struct glyph_row *r1, *r2;
34287 struct glyph *glyph, *end;
34288 ptrdiff_t ignore, pos;
34289 int x;
34290
34291 eassert (NILP (disp_string) || STRINGP (disp_string));
34292 eassert (NILP (before_string) || STRINGP (before_string));
34293 eassert (NILP (after_string) || STRINGP (after_string));
34294
34295
34296 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34297 if (r1 == NULL)
34298 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34299
34300
34301 if (!NILP (before_string) || !NILP (disp_string))
34302 {
34303 struct glyph_row *prev;
34304 while ((prev = r1 - 1, prev >= first)
34305 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34306 && prev->used[TEXT_AREA] > 0)
34307 {
34308 struct glyph *beg = prev->glyphs[TEXT_AREA];
34309 glyph = beg + prev->used[TEXT_AREA];
34310 while (--glyph >= beg && NILP (glyph->object));
34311 if (glyph < beg
34312 || !(EQ (glyph->object, before_string)
34313 || EQ (glyph->object, disp_string)))
34314 break;
34315 r1 = prev;
34316 }
34317 }
34318 if (r2 == NULL)
34319 {
34320 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34321 hlinfo->mouse_face_past_end = true;
34322 }
34323 else if (!NILP (after_string))
34324 {
34325
34326 struct glyph_row *next;
34327 struct glyph_row *last
34328 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34329
34330 for (next = r2 + 1;
34331 next <= last
34332 && next->used[TEXT_AREA] > 0
34333 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34334 ++next)
34335 r2 = next;
34336 }
34337
34338
34339
34340
34341
34342 if (r1->y > r2->y)
34343 {
34344 struct glyph_row *tem = r2;
34345
34346 r2 = r1;
34347 r1 = tem;
34348 }
34349
34350 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34351 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34352
34353
34354
34355
34356
34357
34358
34359
34360
34361
34362
34363 if (!r1->reversed_p)
34364 {
34365
34366
34367 glyph = r1->glyphs[TEXT_AREA];
34368 end = glyph + r1->used[TEXT_AREA];
34369 x = r1->x;
34370
34371
34372 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34373 for (; glyph < end
34374 && NILP (glyph->object)
34375 && glyph->charpos < 0;
34376 ++glyph)
34377 x += glyph->pixel_width;
34378
34379
34380
34381
34382 for (; glyph < end
34383 && !NILP (glyph->object)
34384 && !EQ (glyph->object, disp_string)
34385 && !(BUFFERP (glyph->object)
34386 && (glyph->charpos >= start_charpos
34387 && glyph->charpos < end_charpos));
34388 ++glyph)
34389 {
34390
34391
34392
34393 if (EQ (glyph->object, before_string))
34394 {
34395 pos = string_buffer_position (before_string,
34396 start_charpos);
34397
34398
34399 if (!pos || (pos >= start_charpos && pos < end_charpos))
34400 break;
34401 }
34402 else if (EQ (glyph->object, after_string))
34403 {
34404 pos = string_buffer_position (after_string, end_charpos);
34405 if (!pos || (pos >= start_charpos && pos < end_charpos))
34406 break;
34407 }
34408 x += glyph->pixel_width;
34409 }
34410 hlinfo->mouse_face_beg_x = x;
34411 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34412 }
34413 else
34414 {
34415
34416
34417 struct glyph *g;
34418
34419 end = r1->glyphs[TEXT_AREA] - 1;
34420 glyph = end + r1->used[TEXT_AREA];
34421
34422
34423 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34424 for (; glyph > end
34425 && NILP (glyph->object)
34426 && glyph->charpos < 0;
34427 --glyph)
34428 ;
34429
34430
34431
34432
34433 for (; glyph > end
34434 && !NILP (glyph->object)
34435 && !EQ (glyph->object, disp_string)
34436 && !(BUFFERP (glyph->object)
34437 && (glyph->charpos >= start_charpos
34438 && glyph->charpos < end_charpos));
34439 --glyph)
34440 {
34441
34442
34443
34444 if (EQ (glyph->object, before_string))
34445 {
34446 pos = string_buffer_position (before_string, start_charpos);
34447
34448
34449 if (!pos || (pos >= start_charpos && pos < end_charpos))
34450 break;
34451 }
34452 else if (EQ (glyph->object, after_string))
34453 {
34454 pos = string_buffer_position (after_string, end_charpos);
34455 if (!pos || (pos >= start_charpos && pos < end_charpos))
34456 break;
34457 }
34458 }
34459
34460 glyph++;
34461 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34462 x += g->pixel_width;
34463 hlinfo->mouse_face_beg_x = x;
34464 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34465 }
34466
34467
34468
34469
34470 if (r2 != r1)
34471 {
34472 if (!r2->reversed_p)
34473 {
34474 glyph = r2->glyphs[TEXT_AREA];
34475 end = glyph + r2->used[TEXT_AREA];
34476 x = r2->x;
34477 }
34478 else
34479 {
34480 end = r2->glyphs[TEXT_AREA] - 1;
34481 glyph = end + r2->used[TEXT_AREA];
34482 }
34483 }
34484
34485 if (!r2->reversed_p)
34486 {
34487
34488
34489
34490 while (end > glyph
34491 && NILP ((end - 1)->object))
34492 --end;
34493
34494
34495
34496
34497 for (--end;
34498 end > glyph
34499 && !NILP (end->object)
34500 && !EQ (end->object, disp_string)
34501 && !(BUFFERP (end->object)
34502 && (end->charpos >= start_charpos
34503 && end->charpos < end_charpos));
34504 --end)
34505 {
34506
34507
34508
34509 if (EQ (end->object, before_string))
34510 {
34511 pos = string_buffer_position (before_string, start_charpos);
34512 if (!pos || (pos >= start_charpos && pos < end_charpos))
34513 break;
34514 }
34515 else if (EQ (end->object, after_string))
34516 {
34517 pos = string_buffer_position (after_string, end_charpos);
34518 if (!pos || (pos >= start_charpos && pos < end_charpos))
34519 break;
34520 }
34521 }
34522
34523 for (; glyph <= end; ++glyph)
34524 x += glyph->pixel_width;
34525
34526 hlinfo->mouse_face_end_x = x;
34527 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34528 }
34529 else
34530 {
34531
34532
34533
34534 x = r2->x;
34535 end++;
34536 while (end < glyph
34537 && NILP (end->object))
34538 {
34539 x += end->pixel_width;
34540 ++end;
34541 }
34542
34543
34544
34545
34546 for ( ;
34547 end < glyph
34548 && !NILP (end->object)
34549 && !EQ (end->object, disp_string)
34550 && !(BUFFERP (end->object)
34551 && (end->charpos >= start_charpos
34552 && end->charpos < end_charpos));
34553 ++end)
34554 {
34555
34556
34557
34558 if (EQ (end->object, before_string))
34559 {
34560 pos = string_buffer_position (before_string, start_charpos);
34561 if (!pos || (pos >= start_charpos && pos < end_charpos))
34562 break;
34563 }
34564 else if (EQ (end->object, after_string))
34565 {
34566 pos = string_buffer_position (after_string, end_charpos);
34567 if (!pos || (pos >= start_charpos && pos < end_charpos))
34568 break;
34569 }
34570 x += end->pixel_width;
34571 }
34572
34573
34574
34575
34576
34577 if (end == glyph
34578 && BUFFERP (end->object)
34579 && (end->charpos < start_charpos
34580 || end->charpos >= end_charpos))
34581 {
34582 x += end->pixel_width;
34583 ++end;
34584 }
34585 hlinfo->mouse_face_end_x = x;
34586 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34587 }
34588
34589 hlinfo->mouse_face_window = window;
34590 hlinfo->mouse_face_face_id
34591 = face_at_buffer_position (w, mouse_charpos, &ignore,
34592 mouse_charpos + 1,
34593 !hlinfo->mouse_face_hidden, -1, 0);
34594 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34595 }
34596
34597
34598
34599
34600
34601 #if false
34602
34603
34604
34605
34606
34607
34608
34609
34610
34611
34612
34613
34614
34615
34616
34617
34618 static bool
34619 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34620 int *hpos, int *vpos, int *x, int *y, bool right_p)
34621 {
34622 int yb = window_text_bottom_y (w);
34623 struct glyph_row *r;
34624 struct glyph *best_glyph = NULL;
34625 struct glyph_row *best_row = NULL;
34626 int best_x = 0;
34627
34628 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34629 r->enabled_p && r->y < yb;
34630 ++r)
34631 {
34632 struct glyph *g = r->glyphs[TEXT_AREA];
34633 struct glyph *e = g + r->used[TEXT_AREA];
34634 int gx;
34635
34636 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34637 if (EQ (g->object, object))
34638 {
34639 if (g->charpos == pos)
34640 {
34641 best_glyph = g;
34642 best_x = gx;
34643 best_row = r;
34644 goto found;
34645 }
34646 else if (best_glyph == NULL
34647 || ((eabs (g->charpos - pos)
34648 < eabs (best_glyph->charpos - pos))
34649 && (right_p
34650 ? g->charpos < pos
34651 : g->charpos > pos)))
34652 {
34653 best_glyph = g;
34654 best_x = gx;
34655 best_row = r;
34656 }
34657 }
34658 }
34659
34660 found:
34661
34662 if (best_glyph)
34663 {
34664 *x = best_x;
34665 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34666
34667 if (right_p)
34668 {
34669 *x += best_glyph->pixel_width;
34670 ++*hpos;
34671 }
34672
34673 *y = best_row->y;
34674 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34675 }
34676
34677 return best_glyph != NULL;
34678 }
34679 #endif
34680
34681
34682
34683
34684
34685
34686 static void
34687 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34688 Lisp_Object object,
34689 ptrdiff_t startpos, ptrdiff_t endpos)
34690 {
34691 int yb = window_text_bottom_y (w);
34692 struct glyph_row *r;
34693 struct glyph *g, *e;
34694 int gx;
34695 bool found = false;
34696
34697
34698
34699
34700 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34701 r->enabled_p && r->y < yb;
34702 ++r)
34703 {
34704 if (!r->reversed_p)
34705 {
34706 g = r->glyphs[TEXT_AREA];
34707 e = g + r->used[TEXT_AREA];
34708 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34709 if (EQ (g->object, object)
34710 && startpos <= g->charpos && g->charpos < endpos)
34711 {
34712 hlinfo->mouse_face_beg_row
34713 = MATRIX_ROW_VPOS (r, w->current_matrix);
34714 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34715 hlinfo->mouse_face_beg_x = gx;
34716 found = true;
34717 break;
34718 }
34719 }
34720 else
34721 {
34722 struct glyph *g1;
34723
34724 e = r->glyphs[TEXT_AREA];
34725 g = e + r->used[TEXT_AREA];
34726 for ( ; g > e; --g)
34727 if (EQ ((g-1)->object, object)
34728 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34729 {
34730 hlinfo->mouse_face_beg_row
34731 = MATRIX_ROW_VPOS (r, w->current_matrix);
34732 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34733 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34734 gx += g1->pixel_width;
34735 hlinfo->mouse_face_beg_x = gx;
34736 found = true;
34737 break;
34738 }
34739 }
34740 if (found)
34741 break;
34742 }
34743
34744 if (!found)
34745 return;
34746
34747
34748
34749 for (++r; r->enabled_p && r->y < yb; ++r)
34750 {
34751 g = r->glyphs[TEXT_AREA];
34752 e = g + r->used[TEXT_AREA];
34753 found = false;
34754 for ( ; g < e; ++g)
34755 if (EQ (g->object, object)
34756 && startpos <= g->charpos && g->charpos < endpos)
34757 {
34758 found = true;
34759 break;
34760 }
34761 if (!found)
34762 break;
34763 }
34764
34765
34766 r--;
34767
34768
34769 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34770
34771
34772
34773 if (!r->reversed_p)
34774 {
34775 g = r->glyphs[TEXT_AREA];
34776 e = g + r->used[TEXT_AREA];
34777 for ( ; e > g; --e)
34778 if (EQ ((e-1)->object, object)
34779 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34780 break;
34781 hlinfo->mouse_face_end_col = e - g;
34782
34783 for (gx = r->x; g < e; ++g)
34784 gx += g->pixel_width;
34785 hlinfo->mouse_face_end_x = gx;
34786 }
34787 else
34788 {
34789 e = r->glyphs[TEXT_AREA];
34790 g = e + r->used[TEXT_AREA];
34791 for (gx = r->x ; e < g; ++e)
34792 {
34793 if (EQ (e->object, object)
34794 && startpos <= e->charpos && e->charpos < endpos)
34795 break;
34796 gx += e->pixel_width;
34797 }
34798 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34799 hlinfo->mouse_face_end_x = gx;
34800 }
34801 }
34802
34803 #ifdef HAVE_WINDOW_SYSTEM
34804
34805
34806
34807 static bool
34808 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34809 {
34810 if (!CONSP (hot_spot))
34811 return false;
34812
34813 if (EQ (XCAR (hot_spot), Qrect))
34814 {
34815
34816 Lisp_Object rect = XCDR (hot_spot);
34817 Lisp_Object tem;
34818 if (!CONSP (rect))
34819 return false;
34820 if (!CONSP (XCAR (rect)))
34821 return false;
34822 if (!CONSP (XCDR (rect)))
34823 return false;
34824 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34825 return false;
34826 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34827 return false;
34828 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34829 return false;
34830 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34831 return false;
34832 return true;
34833 }
34834 else if (EQ (XCAR (hot_spot), Qcircle))
34835 {
34836
34837 Lisp_Object circ = XCDR (hot_spot);
34838 Lisp_Object lr, lx0, ly0;
34839 if (CONSP (circ)
34840 && CONSP (XCAR (circ))
34841 && (lr = XCDR (circ), NUMBERP (lr))
34842 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34843 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34844 {
34845 double r = XFLOATINT (lr);
34846 double dx = XFIXNUM (lx0) - x;
34847 double dy = XFIXNUM (ly0) - y;
34848 return (dx * dx + dy * dy <= r * r);
34849 }
34850 }
34851 else if (EQ (XCAR (hot_spot), Qpoly))
34852 {
34853
34854 if (VECTORP (XCDR (hot_spot)))
34855 {
34856 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34857 Lisp_Object *poly = v->contents;
34858 ptrdiff_t n = v->header.size;
34859 ptrdiff_t i;
34860 bool inside = false;
34861 Lisp_Object lx, ly;
34862 int x0, y0;
34863
34864
34865 if (n < 6 || n & 1)
34866 return false;
34867
34868
34869
34870
34871
34872 if ((lx = poly[n-2], !FIXNUMP (lx))
34873 || (ly = poly[n-1], !FIXNUMP (lx)))
34874 return false;
34875 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34876 for (i = 0; i < n; i += 2)
34877 {
34878 int x1 = x0, y1 = y0;
34879 if ((lx = poly[i], !FIXNUMP (lx))
34880 || (ly = poly[i+1], !FIXNUMP (ly)))
34881 return false;
34882 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34883
34884
34885 if (x0 >= x)
34886 {
34887 if (x1 >= x)
34888 continue;
34889 }
34890 else if (x1 < x)
34891 continue;
34892 if (y > y0 && y > y1)
34893 continue;
34894 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34895 inside = !inside;
34896 }
34897 return inside;
34898 }
34899 }
34900 return false;
34901 }
34902
34903 Lisp_Object
34904 find_hot_spot (Lisp_Object map, int x, int y)
34905 {
34906 while (CONSP (map))
34907 {
34908 if (CONSP (XCAR (map))
34909 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34910 return XCAR (map);
34911 map = XCDR (map);
34912 }
34913
34914 return Qnil;
34915 }
34916
34917 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34918 3, 3, 0,
34919 doc:
34920
34921
34922
34923
34924
34925
34926
34927
34928 )
34929 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34930 {
34931 if (NILP (map))
34932 return Qnil;
34933
34934 CHECK_FIXNUM (x);
34935 CHECK_FIXNUM (y);
34936
34937 return find_hot_spot (map,
34938 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34939 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34940 }
34941 #endif
34942
34943
34944
34945 static void
34946 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34947 {
34948 #ifdef HAVE_WINDOW_SYSTEM
34949 if (!FRAME_WINDOW_P (f))
34950 return;
34951
34952
34953 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34954 || EQ (track_mouse, Qdrag_source))
34955 return;
34956
34957 if (!NILP (pointer))
34958 {
34959 if (EQ (pointer, Qarrow))
34960 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34961 else if (EQ (pointer, Qhand))
34962 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34963 else if (EQ (pointer, Qtext))
34964 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
34965 else if (EQ (pointer, intern ("hdrag")))
34966 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
34967 else if (EQ (pointer, intern ("nhdrag")))
34968 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34969 # ifdef HAVE_X_WINDOWS
34970 else if (EQ (pointer, intern ("vdrag")))
34971 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
34972 # endif
34973 else if (EQ (pointer, intern ("hourglass")))
34974 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
34975 else if (EQ (pointer, Qmodeline))
34976 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
34977 else
34978 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34979 }
34980
34981 if (cursor != No_Cursor)
34982 FRAME_RIF (f)->define_frame_cursor (f, cursor);
34983 #endif
34984 }
34985
34986
34987
34988
34989
34990
34991
34992 static void
34993 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
34994 enum window_part area)
34995 {
34996 struct window *w = XWINDOW (window);
34997 struct frame *f = XFRAME (w->frame);
34998 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
34999 Emacs_Cursor cursor = No_Cursor;
35000 Lisp_Object pointer = Qnil;
35001 int dx, dy, width, height;
35002 ptrdiff_t charpos;
35003 Lisp_Object string, object = Qnil;
35004 Lisp_Object pos UNINIT;
35005 Lisp_Object mouse_face;
35006 int original_x_pixel = x;
35007 struct glyph * glyph = NULL, * row_start_glyph = NULL;
35008 struct glyph_row *row UNINIT;
35009
35010 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
35011 {
35012 int x0;
35013 struct glyph *end;
35014
35015
35016
35017 string = mode_line_string (w, area, &x, &y, &charpos,
35018 &object, &dx, &dy, &width, &height);
35019
35020 row = (area == ON_MODE_LINE
35021 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
35022 : (area == ON_TAB_LINE
35023 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
35024 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
35025
35026
35027 if (row->mode_line_p && row->enabled_p)
35028 {
35029 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
35030 end = glyph + row->used[TEXT_AREA];
35031
35032 for (x0 = original_x_pixel;
35033 glyph < end && x0 >= glyph->pixel_width;
35034 ++glyph)
35035 x0 -= glyph->pixel_width;
35036
35037 if (glyph >= end)
35038 glyph = NULL;
35039 }
35040 }
35041 else
35042 {
35043 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
35044
35045
35046 string = marginal_area_string (w, area, &x, &y, &charpos,
35047 &object, &dx, &dy, &width, &height);
35048 }
35049
35050 Lisp_Object help = Qnil;
35051
35052 #ifdef HAVE_WINDOW_SYSTEM
35053 if (IMAGEP (object))
35054 {
35055 Lisp_Object image_map, hotspot;
35056 if ((image_map = plist_get (XCDR (object), QCmap),
35057 !NILP (image_map))
35058 && (hotspot = find_hot_spot (image_map, dx, dy),
35059 CONSP (hotspot))
35060 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35061 {
35062 Lisp_Object plist;
35063
35064
35065
35066
35067 hotspot = XCDR (hotspot);
35068 if (CONSP (hotspot)
35069 && (plist = XCAR (hotspot), CONSP (plist)))
35070 {
35071 pointer = plist_get (plist, Qpointer);
35072 if (NILP (pointer))
35073 pointer = Qhand;
35074 help = plist_get (plist, Qhelp_echo);
35075 if (!NILP (help))
35076 {
35077 help_echo_string = help;
35078 XSETWINDOW (help_echo_window, w);
35079 help_echo_object = w->contents;
35080 help_echo_pos = charpos;
35081 }
35082 }
35083 }
35084 if (NILP (pointer))
35085 pointer = plist_get (XCDR (object), QCpointer);
35086 }
35087 #endif
35088
35089
35090
35091
35092 if (STRINGP (string))
35093 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
35094
35095
35096
35097
35098
35099 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
35100 || area == ON_TAB_LINE)
35101 {
35102
35103
35104 if (NILP (help))
35105 {
35106 if (STRINGP (string))
35107 help = Fget_text_property (pos, Qhelp_echo, string);
35108
35109 if (!NILP (help))
35110 {
35111 help_echo_string = help;
35112 XSETWINDOW (help_echo_window, w);
35113 help_echo_object = string;
35114 help_echo_pos = charpos;
35115 }
35116 else if (area == ON_MODE_LINE
35117 && !NILP (w->mode_line_help_echo))
35118 {
35119 help_echo_string = w->mode_line_help_echo;
35120 XSETWINDOW (help_echo_window, w);
35121 help_echo_object = Qnil;
35122 help_echo_pos = -1;
35123 }
35124 }
35125
35126 #ifdef HAVE_WINDOW_SYSTEM
35127
35128 if (FRAME_WINDOW_P (f))
35129 {
35130 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
35131 || minibuf_level
35132 || NILP (Vresize_mini_windows));
35133
35134 if (STRINGP (string))
35135 {
35136 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35137
35138 if (NILP (pointer))
35139 pointer = Fget_text_property (pos, Qpointer, string);
35140
35141
35142 if (NILP (pointer)
35143 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
35144 || area == ON_TAB_LINE))
35145 {
35146 Lisp_Object map;
35147
35148 map = Fget_text_property (pos, Qlocal_map, string);
35149 if (!KEYMAPP (map))
35150 map = Fget_text_property (pos, Qkeymap, string);
35151 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
35152 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35153 }
35154 }
35155 else if (draggable && area == ON_MODE_LINE)
35156 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35157 else if ((area == ON_MODE_LINE
35158 && WINDOW_BOTTOMMOST_P (w)
35159 && !FRAME_HAS_MINIBUF_P (f)
35160 && !NILP (Fframe_parameter
35161 (w->frame, Qdrag_with_mode_line)))
35162 || (((area == ON_HEADER_LINE
35163 && !NILP (Fframe_parameter
35164 (w->frame, Qdrag_with_header_line)))
35165 || (area == ON_TAB_LINE
35166 && !NILP (Fframe_parameter
35167 (w->frame, Qdrag_with_tab_line))))
35168 && WINDOW_TOPMOST_P (w)))
35169 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35170 else
35171 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35172 }
35173 #endif
35174 }
35175
35176
35177 bool mouse_face_shown = false;
35178
35179 if (STRINGP (string))
35180 {
35181 mouse_face = Fget_text_property (pos, Qmouse_face, string);
35182 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
35183 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
35184 || (area == ON_TAB_LINE))
35185 && glyph)
35186 {
35187 Lisp_Object b, e;
35188
35189 struct glyph * tmp_glyph;
35190
35191 int gpos;
35192 int gseq_length;
35193 int total_pixel_width;
35194 ptrdiff_t begpos, endpos, ignore;
35195
35196 int vpos, hpos;
35197
35198 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
35199 Qmouse_face, string, Qnil);
35200 if (NILP (b))
35201 begpos = 0;
35202 else
35203 begpos = XFIXNUM (b);
35204
35205 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
35206 if (NILP (e))
35207 endpos = SCHARS (string);
35208 else
35209 endpos = XFIXNUM (e);
35210
35211
35212
35213
35214
35215
35216
35217
35218
35219
35220
35221 tmp_glyph = row_start_glyph;
35222 while (tmp_glyph < glyph
35223 && (!(EQ (tmp_glyph->object, glyph->object)
35224 && begpos <= tmp_glyph->charpos
35225 && tmp_glyph->charpos < endpos)))
35226 tmp_glyph++;
35227 gpos = glyph - tmp_glyph;
35228
35229
35230
35231
35232
35233
35234 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
35235 tmp_glyph > glyph
35236 && (!(EQ (tmp_glyph->object, glyph->object)
35237 && begpos <= tmp_glyph->charpos
35238 && tmp_glyph->charpos < endpos));
35239 tmp_glyph--)
35240 ;
35241 gseq_length = gpos + (tmp_glyph - glyph) + 1;
35242
35243
35244
35245 total_pixel_width = 0;
35246 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
35247 total_pixel_width += tmp_glyph->pixel_width;
35248
35249
35250
35251
35252 hpos = x - gpos;
35253 vpos = (area == ON_MODE_LINE
35254 ? (w->current_matrix)->nrows - 1
35255 : (area == ON_TAB_LINE
35256 ? 0
35257 : (w->current_matrix->tab_line_p
35258 ? 1
35259 : 0)));
35260
35261
35262
35263 if ( EQ (window, hlinfo->mouse_face_window)
35264 && (!row->reversed_p
35265 ? (hlinfo->mouse_face_beg_col <= hpos
35266 && hpos < hlinfo->mouse_face_end_col)
35267
35268 : (hlinfo->mouse_face_end_col <= hpos
35269 && hpos < hlinfo->mouse_face_beg_col))
35270 && hlinfo->mouse_face_beg_row == vpos )
35271 return;
35272
35273 if (clear_mouse_face (hlinfo))
35274 cursor = No_Cursor;
35275
35276 if (!row->reversed_p)
35277 {
35278 hlinfo->mouse_face_beg_col = hpos;
35279 hlinfo->mouse_face_beg_x = original_x_pixel
35280 - (total_pixel_width + dx);
35281 hlinfo->mouse_face_end_col = hpos + gseq_length;
35282 hlinfo->mouse_face_end_x = 0;
35283 }
35284 else
35285 {
35286
35287
35288 hlinfo->mouse_face_end_col = hpos;
35289 hlinfo->mouse_face_end_x = original_x_pixel
35290 - (total_pixel_width + dx);
35291 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35292 hlinfo->mouse_face_beg_x = 0;
35293 }
35294
35295 hlinfo->mouse_face_beg_row = vpos;
35296 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35297 hlinfo->mouse_face_past_end = false;
35298 hlinfo->mouse_face_window = window;
35299
35300 hlinfo->mouse_face_face_id =
35301 face_at_string_position (w, string, charpos, 0, &ignore,
35302 glyph->face_id, true, 0);
35303
35304 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35305 mouse_face_shown = true;
35306
35307 if (NILP (pointer))
35308 pointer = Qhand;
35309 }
35310 }
35311
35312
35313
35314 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35315 || area == ON_TAB_LINE) && !mouse_face_shown)
35316 clear_mouse_face (hlinfo);
35317
35318 define_frame_cursor1 (f, cursor, pointer);
35319 }
35320
35321
35322
35323
35324
35325
35326
35327
35328
35329
35330 void
35331 note_mouse_highlight (struct frame *f, int x, int y)
35332 {
35333 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35334 enum window_part part = ON_NOTHING;
35335 Lisp_Object window;
35336 struct window *w;
35337 Emacs_Cursor cursor = No_Cursor;
35338 Lisp_Object pointer = Qnil;
35339 struct buffer *b;
35340
35341
35342 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS) \
35343 || defined (HAVE_ANDROID)
35344 if (popup_activated ())
35345 return;
35346 #endif
35347
35348 #if defined (HAVE_HAIKU)
35349 if (popup_activated_p)
35350 return;
35351 #endif
35352
35353 if (!f->glyphs_initialized_p
35354 || f->pointer_invisible)
35355 return;
35356
35357 hlinfo->mouse_face_mouse_x = x;
35358 hlinfo->mouse_face_mouse_y = y;
35359 hlinfo->mouse_face_mouse_frame = f;
35360
35361 if (hlinfo->mouse_face_defer)
35362 return;
35363
35364
35365 window = window_from_coordinates (f, x, y, &part, true, true);
35366
35367
35368 if (! EQ (window, hlinfo->mouse_face_window)
35369
35370 || (!NILP (hlinfo->mouse_face_window)
35371 && !NILP (window)
35372 && part != ON_TEXT
35373 && part != ON_MODE_LINE
35374 && part != ON_HEADER_LINE
35375 && part != ON_TAB_LINE))
35376 clear_mouse_face (hlinfo);
35377
35378
35379 help_echo_string = Qnil;
35380
35381
35382 if (!FRAME_WINDOW_P (f)
35383 && (y >= FRAME_MENU_BAR_LINES (f)
35384 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35385 {
35386 int prop_idx;
35387 bool ignore;
35388 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35389
35390 if (!NILP (caption))
35391 {
35392 help_echo_object = help_echo_window = Qnil;
35393 help_echo_pos = -1;
35394 help_echo_string = AREF (f->tab_bar_items,
35395 prop_idx * TAB_BAR_ITEM_NSLOTS
35396 + TAB_BAR_ITEM_HELP);
35397 if (NILP (help_echo_string))
35398 help_echo_string = caption;
35399 }
35400 }
35401
35402 #ifdef HAVE_WINDOW_SYSTEM
35403
35404
35405 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35406 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35407 {
35408 enum internal_border_part part = frame_internal_border_part (f, x, y);
35409
35410 switch (part)
35411 {
35412 case INTERNAL_BORDER_NONE:
35413 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35414
35415 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35416 break;
35417 case INTERNAL_BORDER_LEFT_EDGE:
35418 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35419 break;
35420 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35421 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35422 break;
35423 case INTERNAL_BORDER_TOP_EDGE:
35424 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35425 break;
35426 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35427 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35428 break;
35429 case INTERNAL_BORDER_RIGHT_EDGE:
35430 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35431 break;
35432 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35433 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35434 break;
35435 case INTERNAL_BORDER_BOTTOM_EDGE:
35436 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35437 break;
35438 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35439 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35440 break;
35441 default:
35442
35443 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35444 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35445 }
35446
35447 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35448 {
35449
35450 help_echo_string = build_string ("drag-mouse-1: resize frame");
35451 goto set_cursor;
35452 }
35453 }
35454 #endif
35455
35456
35457 if (!WINDOWP (window))
35458 return;
35459
35460
35461 w = XWINDOW (window);
35462 frame_to_window_pixel_xy (w, &x, &y);
35463
35464 #if defined (HAVE_WINDOW_SYSTEM)
35465
35466
35467 if (EQ (window, f->tab_bar_window))
35468 {
35469 note_tab_bar_highlight (f, x, y);
35470 if (tab_bar__dragging_in_progress)
35471 {
35472 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35473 goto set_cursor;
35474 }
35475 else
35476 return;
35477 }
35478 else
35479 {
35480
35481
35482
35483
35484 f->last_tab_bar_item = -1;
35485 }
35486 #endif
35487
35488 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35489
35490
35491 if (EQ (window, f->tool_bar_window))
35492 {
35493 note_tool_bar_highlight (f, x, y);
35494 return;
35495 }
35496 #endif
35497
35498
35499 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35500 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35501 {
35502 note_mode_line_or_margin_highlight (window, x, y, part);
35503
35504 #ifdef HAVE_WINDOW_SYSTEM
35505 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35506 {
35507 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35508
35509 goto set_cursor;
35510 }
35511 else
35512 #endif
35513 return;
35514 }
35515
35516 #ifdef HAVE_WINDOW_SYSTEM
35517 if (part == ON_VERTICAL_BORDER)
35518 {
35519 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35520 help_echo_string = build_string ("drag-mouse-1: resize");
35521 goto set_cursor;
35522 }
35523 else if (part == ON_RIGHT_DIVIDER)
35524 {
35525 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35526 help_echo_string = build_string ("drag-mouse-1: resize");
35527 goto set_cursor;
35528 }
35529 else if (part == ON_BOTTOM_DIVIDER)
35530 if (! WINDOW_BOTTOMMOST_P (w)
35531 || minibuf_level
35532 || NILP (Vresize_mini_windows))
35533 {
35534 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35535 help_echo_string = build_string ("drag-mouse-1: resize");
35536 goto set_cursor;
35537 }
35538 else
35539 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35540 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35541 || part == ON_VERTICAL_SCROLL_BAR
35542 || part == ON_HORIZONTAL_SCROLL_BAR)
35543 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35544 else
35545 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35546 #endif
35547
35548
35549
35550 b = XBUFFER (w->contents);
35551 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35552 {
35553 int hpos, vpos, dx, dy, area = LAST_AREA;
35554 ptrdiff_t pos;
35555 struct glyph *glyph;
35556 Lisp_Object object;
35557 Lisp_Object mouse_face = Qnil, position;
35558 Lisp_Object *overlay_vec = NULL;
35559 ptrdiff_t i, noverlays;
35560 struct buffer *obuf;
35561 ptrdiff_t obegv, ozv;
35562 bool same_region;
35563
35564
35565 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35566
35567 #ifdef HAVE_WINDOW_SYSTEM
35568
35569 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35570 {
35571 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35572 if (img != NULL && IMAGEP (img->spec))
35573 {
35574 Lisp_Object image_map, hotspot;
35575 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35576 !NILP (image_map))
35577 && (hotspot = find_hot_spot (image_map,
35578 glyph->slice.img.x + dx,
35579 glyph->slice.img.y + dy),
35580 CONSP (hotspot))
35581 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35582 {
35583 Lisp_Object plist;
35584
35585
35586
35587
35588
35589 hotspot = XCDR (hotspot);
35590 if (CONSP (hotspot)
35591 && (plist = XCAR (hotspot), CONSP (plist)))
35592 {
35593 pointer = plist_get (plist, Qpointer);
35594 if (NILP (pointer))
35595 pointer = Qhand;
35596 help_echo_string = plist_get (plist, Qhelp_echo);
35597 if (!NILP (help_echo_string))
35598 {
35599 help_echo_window = window;
35600 help_echo_object = glyph->object;
35601 help_echo_pos = glyph->charpos;
35602 }
35603 }
35604 }
35605 if (NILP (pointer))
35606 pointer = plist_get (XCDR (img->spec), QCpointer);
35607 }
35608 }
35609 #endif
35610
35611
35612 if (glyph == NULL
35613 || area != TEXT_AREA
35614 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35615
35616
35617
35618
35619
35620 || NILP (glyph->object)
35621
35622
35623
35624
35625 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35626 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35627 && glyph->type == STRETCH_GLYPH
35628 && glyph->avoid_cursor_p))
35629 {
35630 if (clear_mouse_face (hlinfo))
35631 cursor = No_Cursor;
35632 if (FRAME_WINDOW_P (f) && NILP (pointer))
35633 {
35634 #ifdef HAVE_WINDOW_SYSTEM
35635 if (area != TEXT_AREA)
35636 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35637 else
35638 pointer = Vvoid_text_area_pointer;
35639 #endif
35640 }
35641 goto set_cursor;
35642 }
35643
35644 pos = glyph->charpos;
35645 object = glyph->object;
35646 if (!STRINGP (object) && !BUFFERP (object))
35647 goto set_cursor;
35648
35649
35650 if (BUFFERP (object) && pos > BUF_Z (b))
35651 goto set_cursor;
35652
35653
35654
35655 obuf = current_buffer;
35656 current_buffer = b;
35657 obegv = BEGV;
35658 ozv = ZV;
35659 BEGV = BEG;
35660 ZV = Z;
35661
35662
35663 position = make_fixnum (pos);
35664
35665 USE_SAFE_ALLOCA;
35666
35667 if (BUFFERP (object))
35668 {
35669
35670 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35671
35672 noverlays = sort_overlays (overlay_vec, noverlays, w);
35673 }
35674 else
35675 noverlays = 0;
35676
35677 if (NILP (Vmouse_highlight))
35678 {
35679 clear_mouse_face (hlinfo);
35680 goto check_help_echo;
35681 }
35682
35683 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35684
35685 if (same_region)
35686 cursor = No_Cursor;
35687
35688
35689 if (! same_region
35690
35691
35692
35693
35694
35695 || (!hlinfo->mouse_face_hidden
35696 && OVERLAYP (hlinfo->mouse_face_overlay)
35697
35698 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35699 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35700 {
35701
35702 Lisp_Object overlay = Qnil;
35703 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35704 {
35705 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35706 if (!NILP (mouse_face))
35707 overlay = overlay_vec[i];
35708 }
35709
35710
35711
35712 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35713 goto check_help_echo;
35714
35715
35716 if (clear_mouse_face (hlinfo))
35717 cursor = No_Cursor;
35718
35719
35720 hlinfo->mouse_face_overlay = overlay;
35721
35722
35723 if (NILP (overlay))
35724 mouse_face = Fget_text_property (position, Qmouse_face, object);
35725
35726
35727
35728 if (!NILP (mouse_face) && STRINGP (object))
35729 {
35730
35731
35732 Lisp_Object s, e;
35733 ptrdiff_t ignore;
35734
35735 s = Fprevious_single_property_change
35736 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35737 e = Fnext_single_property_change
35738 (position, Qmouse_face, object, Qnil);
35739 if (NILP (s))
35740 s = make_fixnum (0);
35741 if (NILP (e))
35742 e = make_fixnum (SCHARS (object));
35743 mouse_face_from_string_pos (w, hlinfo, object,
35744 XFIXNUM (s), XFIXNUM (e));
35745 hlinfo->mouse_face_past_end = false;
35746 hlinfo->mouse_face_window = window;
35747 hlinfo->mouse_face_face_id
35748 = face_at_string_position (w, object, pos, 0, &ignore,
35749 glyph->face_id, true, 0);
35750 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35751 cursor = No_Cursor;
35752 }
35753 else
35754 {
35755
35756
35757 Lisp_Object buffer UNINIT;
35758 Lisp_Object disp_string UNINIT;
35759
35760 if (STRINGP (object))
35761 {
35762
35763
35764 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35765 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35766 pos = string_buffer_position (object, start);
35767 if (pos > 0)
35768 {
35769 mouse_face = get_char_property_and_overlay
35770 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35771 buffer = w->contents;
35772 disp_string = object;
35773 }
35774 }
35775 else
35776 {
35777 buffer = object;
35778 disp_string = Qnil;
35779 }
35780
35781 if (!NILP (mouse_face))
35782 {
35783 Lisp_Object before, after;
35784 Lisp_Object before_string, after_string;
35785
35786
35787
35788
35789
35790
35791
35792
35793
35794
35795 Lisp_Object lim1
35796 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35797 ? Fmarker_position (w->start)
35798 : Qnil;
35799 Lisp_Object lim2
35800 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35801 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35802 - w->window_end_pos)
35803 : Qnil;
35804
35805 if (NILP (overlay))
35806 {
35807
35808 before = Fprevious_single_property_change
35809 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35810 after = Fnext_single_property_change
35811 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35812 before_string = after_string = Qnil;
35813 }
35814 else
35815 {
35816
35817 before = Foverlay_start (overlay);
35818 after = Foverlay_end (overlay);
35819 before_string = Foverlay_get (overlay, Qbefore_string);
35820 after_string = Foverlay_get (overlay, Qafter_string);
35821
35822 if (!STRINGP (before_string)) before_string = Qnil;
35823 if (!STRINGP (after_string)) after_string = Qnil;
35824 }
35825
35826 mouse_face_from_buffer_pos (window, hlinfo, pos,
35827 NILP (before)
35828 ? 1
35829 : XFIXNAT (before),
35830 NILP (after)
35831 ? BUF_Z (XBUFFER (buffer))
35832 : XFIXNAT (after),
35833 before_string, after_string,
35834 disp_string);
35835 cursor = No_Cursor;
35836 }
35837 }
35838 }
35839
35840 check_help_echo:
35841
35842
35843 if (NILP (help_echo_string)) {
35844 Lisp_Object help, overlay;
35845
35846
35847 help = overlay = Qnil;
35848 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35849 {
35850 overlay = overlay_vec[i];
35851 help = Foverlay_get (overlay, Qhelp_echo);
35852 }
35853
35854 if (!NILP (help))
35855 {
35856 help_echo_string = help;
35857 help_echo_window = window;
35858 help_echo_object = overlay;
35859 help_echo_pos = pos;
35860 }
35861 else
35862 {
35863 Lisp_Object obj = glyph->object;
35864 ptrdiff_t charpos = glyph->charpos;
35865
35866
35867 if (STRINGP (obj)
35868 && charpos >= 0
35869 && charpos < SCHARS (obj))
35870 {
35871 help = Fget_text_property (make_fixnum (charpos),
35872 Qhelp_echo, obj);
35873 if (NILP (help))
35874 {
35875
35876
35877 struct glyph_row *r
35878 = MATRIX_ROW (w->current_matrix, vpos);
35879 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35880 ptrdiff_t p = string_buffer_position (obj, start);
35881 if (p > 0)
35882 {
35883 help = Fget_char_property (make_fixnum (p),
35884 Qhelp_echo, w->contents);
35885 if (!NILP (help))
35886 {
35887 charpos = p;
35888 obj = w->contents;
35889 }
35890 }
35891 }
35892 }
35893 else if (BUFFERP (obj)
35894 && charpos >= BEGV
35895 && charpos < ZV)
35896 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35897 obj);
35898
35899 if (!NILP (help))
35900 {
35901 help_echo_string = help;
35902 help_echo_window = window;
35903 help_echo_object = obj;
35904 help_echo_pos = charpos;
35905 }
35906 }
35907 }
35908
35909 #ifdef HAVE_WINDOW_SYSTEM
35910
35911 if (FRAME_WINDOW_P (f) && NILP (pointer))
35912 {
35913
35914 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35915 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35916
35917 if (NILP (pointer))
35918 {
35919 Lisp_Object obj = glyph->object;
35920 ptrdiff_t charpos = glyph->charpos;
35921
35922
35923 if (STRINGP (obj)
35924 && charpos >= 0
35925 && charpos < SCHARS (obj))
35926 {
35927 pointer = Fget_text_property (make_fixnum (charpos),
35928 Qpointer, obj);
35929 if (NILP (pointer))
35930 {
35931
35932
35933 struct glyph_row *r
35934 = MATRIX_ROW (w->current_matrix, vpos);
35935 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35936 ptrdiff_t p = string_buffer_position (obj, start);
35937 if (p > 0)
35938 pointer = Fget_char_property (make_fixnum (p),
35939 Qpointer, w->contents);
35940 }
35941 }
35942 else if (BUFFERP (obj)
35943 && charpos >= BEGV
35944 && charpos < ZV)
35945 pointer = Fget_text_property (make_fixnum (charpos),
35946 Qpointer, obj);
35947 }
35948 }
35949 #endif
35950
35951 BEGV = obegv;
35952 ZV = ozv;
35953 current_buffer = obuf;
35954 SAFE_FREE ();
35955 }
35956
35957 set_cursor:
35958 define_frame_cursor1 (f, cursor, pointer);
35959 }
35960
35961
35962
35963
35964
35965
35966
35967 void
35968 gui_clear_window_mouse_face (struct window *w)
35969 {
35970 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
35971 Lisp_Object window;
35972
35973 block_input ();
35974 XSETWINDOW (window, w);
35975 if (EQ (window, hlinfo->mouse_face_window))
35976 clear_mouse_face (hlinfo);
35977 unblock_input ();
35978 }
35979
35980
35981
35982
35983
35984
35985 void
35986 cancel_mouse_face (struct frame *f)
35987 {
35988 Lisp_Object window;
35989 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35990
35991 window = hlinfo->mouse_face_window;
35992 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
35993 reset_mouse_highlight (hlinfo);
35994 }
35995
35996
35997
35998
35999
36000
36001
36002 #ifdef HAVE_WINDOW_SYSTEM
36003
36004
36005
36006
36007 static void
36008 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
36009 enum glyph_row_area area)
36010 {
36011 struct glyph *first = row->glyphs[area];
36012 struct glyph *end = row->glyphs[area] + row->used[area];
36013 struct glyph *last;
36014 int first_x, start_x, x;
36015
36016 if (area == TEXT_AREA && row->fill_line_p)
36017
36018 draw_glyphs (w, row->x, row, area,
36019 0, row->used[area],
36020 DRAW_NORMAL_TEXT, 0);
36021 else
36022 {
36023
36024
36025
36026 start_x = window_box_left_offset (w, area);
36027 x = start_x;
36028 if (area == TEXT_AREA)
36029 x += row->x;
36030
36031
36032 while (first < end
36033 && x + first->pixel_width < r->x)
36034 {
36035 x += first->pixel_width;
36036 ++first;
36037 }
36038
36039
36040 last = first;
36041 first_x = x;
36042
36043
36044
36045 int r_end = r->x + r->width;
36046 while (last < end && x < r_end)
36047 {
36048 x += last->pixel_width;
36049 ++last;
36050 }
36051
36052
36053 if (last > first)
36054 draw_glyphs (w, first_x - start_x, row, area,
36055 first - row->glyphs[area], last - row->glyphs[area],
36056 DRAW_NORMAL_TEXT, 0);
36057 }
36058 }
36059
36060
36061
36062
36063
36064
36065 static bool
36066 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
36067 {
36068 eassert (row->enabled_p);
36069
36070 if (row->mode_line_p || w->pseudo_window_p)
36071 draw_glyphs (w, 0, row, TEXT_AREA,
36072 0, row->used[TEXT_AREA],
36073 DRAW_NORMAL_TEXT, 0);
36074 else
36075 {
36076 if (row->used[LEFT_MARGIN_AREA])
36077 expose_area (w, row, r, LEFT_MARGIN_AREA);
36078 if (row->used[TEXT_AREA])
36079 expose_area (w, row, r, TEXT_AREA);
36080 if (row->used[RIGHT_MARGIN_AREA])
36081 expose_area (w, row, r, RIGHT_MARGIN_AREA);
36082 draw_row_fringe_bitmaps (w, row);
36083 }
36084
36085 return row->mouse_face_p;
36086 }
36087
36088
36089
36090
36091
36092
36093
36094
36095
36096
36097 static void
36098 expose_overlaps (struct window *w,
36099 struct glyph_row *first_overlapping_row,
36100 struct glyph_row *last_overlapping_row,
36101 const Emacs_Rectangle *r)
36102 {
36103 struct glyph_row *row;
36104
36105 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
36106 if (row->overlapping_p)
36107 {
36108 eassert (row->enabled_p && !row->mode_line_p);
36109
36110 row->clip = r;
36111 if (row->used[LEFT_MARGIN_AREA])
36112 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
36113
36114 if (row->used[TEXT_AREA])
36115 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
36116
36117 if (row->used[RIGHT_MARGIN_AREA])
36118 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
36119 row->clip = NULL;
36120 }
36121 }
36122
36123
36124
36125
36126 static bool
36127 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
36128 {
36129 Emacs_Rectangle cr, result;
36130 struct glyph *cursor_glyph;
36131 struct glyph_row *row;
36132
36133 if (w->phys_cursor.vpos >= 0
36134 && w->phys_cursor.vpos < w->current_matrix->nrows
36135 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
36136 row->enabled_p)
36137 && row->cursor_in_fringe_p)
36138 {
36139
36140 cr.x = window_box_right_offset (w,
36141 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
36142 ? RIGHT_MARGIN_AREA
36143 : TEXT_AREA));
36144 cr.y = row->y;
36145 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
36146 cr.height = row->height;
36147 return gui_intersect_rectangles (&cr, r, &result);
36148 }
36149
36150 cursor_glyph = get_phys_cursor_glyph (w);
36151 if (cursor_glyph)
36152 {
36153
36154
36155 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
36156 cr.y = w->phys_cursor.y;
36157 cr.width = cursor_glyph->pixel_width;
36158 cr.height = w->phys_cursor_height;
36159
36160
36161 return gui_intersect_rectangles (&cr, r, &result);
36162 }
36163
36164 return false;
36165 }
36166
36167
36168
36169
36170
36171
36172 void
36173 gui_draw_vertical_border (struct window *w)
36174 {
36175 struct frame *f = XFRAME (WINDOW_FRAME (w));
36176
36177
36178
36179
36180
36181
36182
36183
36184
36185 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
36186 return;
36187
36188
36189
36190
36191 if (!WINDOW_RIGHTMOST_P (w)
36192 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
36193 {
36194 int x0, x1, y0, y1;
36195
36196 window_box_edges (w, &x0, &y0, &x1, &y1);
36197 y1 -= 1;
36198
36199 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36200 x1 -= 1;
36201
36202 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
36203 }
36204
36205 if (!WINDOW_LEFTMOST_P (w)
36206 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
36207 {
36208 int x0, x1, y0, y1;
36209
36210 window_box_edges (w, &x0, &y0, &x1, &y1);
36211 y1 -= 1;
36212
36213 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36214 x0 -= 1;
36215
36216 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
36217 }
36218 }
36219
36220
36221
36222
36223 void
36224 gui_draw_right_divider (struct window *w)
36225 {
36226 struct frame *f = WINDOW_XFRAME (w);
36227
36228 if (w->mini || w->pseudo_window_p)
36229 return;
36230 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36231 {
36232 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
36233 int x1 = WINDOW_RIGHT_EDGE_X (w);
36234 int y0 = WINDOW_TOP_EDGE_Y (w);
36235 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36236
36237
36238
36239 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
36240 && !NILP (w->parent)
36241 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
36242 && !NILP (w->next))
36243 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36244
36245 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36246 }
36247 }
36248
36249 static void
36250 gui_draw_bottom_divider (struct window *w)
36251 {
36252 struct frame *f = XFRAME (WINDOW_FRAME (w));
36253
36254 if (w->mini || w->pseudo_window_p)
36255 return;
36256 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36257 {
36258 int x0 = WINDOW_LEFT_EDGE_X (w);
36259 int x1 = WINDOW_RIGHT_EDGE_X (w);
36260 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36261 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36262 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36263
36264
36265
36266 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36267 && p
36268 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36269 && !NILP (w->next))
36270 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36271 && NILP (w->next)
36272 && !NILP (p->parent)
36273 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36274 && !NILP (XWINDOW (p->parent)->next))))
36275 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36276
36277 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36278 }
36279 }
36280
36281
36282
36283
36284
36285
36286 static bool
36287 expose_window (struct window *w, const Emacs_Rectangle *fr)
36288 {
36289 struct frame *f = XFRAME (w->frame);
36290 Emacs_Rectangle wr, r;
36291 bool mouse_face_overwritten_p = false;
36292
36293
36294
36295
36296
36297 if (w->current_matrix == NULL)
36298 return false;
36299
36300
36301
36302
36303 if (w->must_be_updated_p)
36304 {
36305 SET_FRAME_GARBAGED (f);
36306 return false;
36307 }
36308
36309
36310 wr.x = WINDOW_LEFT_EDGE_X (w);
36311 wr.y = WINDOW_TOP_EDGE_Y (w);
36312 wr.width = WINDOW_PIXEL_WIDTH (w);
36313 wr.height = WINDOW_PIXEL_HEIGHT (w);
36314
36315 if (gui_intersect_rectangles (fr, &wr, &r))
36316 {
36317 int yb = window_text_bottom_y (w);
36318 struct glyph_row *row;
36319 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36320
36321 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36322 r.x, r.y, r.width, r.height);
36323
36324
36325 r.x -= WINDOW_LEFT_EDGE_X (w);
36326 r.y -= WINDOW_TOP_EDGE_Y (w);
36327
36328
36329 bool cursor_cleared_p = (!w->pseudo_window_p
36330 && phys_cursor_in_rect_p (w, &r));
36331 if (cursor_cleared_p)
36332 gui_clear_cursor (w);
36333
36334
36335
36336
36337
36338
36339 bool phys_cursor_on_p = w->phys_cursor_on_p;
36340
36341
36342
36343
36344 int r_bottom = r.y + r.height;
36345
36346
36347
36348
36349
36350 bool buffer_changed = false;
36351 struct buffer *oldbuf = current_buffer;
36352 if (!w->pseudo_window_p)
36353 {
36354 set_buffer_internal_1 (XBUFFER (w->contents));
36355 buffer_changed = true;
36356 }
36357
36358
36359 first_overlapping_row = last_overlapping_row = NULL;
36360 for (row = w->current_matrix->rows;
36361 row->enabled_p;
36362 ++row)
36363 {
36364 int y0 = row->y;
36365 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36366
36367 if ((y0 >= r.y && y0 < r_bottom)
36368 || (y1 > r.y && y1 < r_bottom)
36369 || (r.y >= y0 && r.y < y1)
36370 || (r_bottom > y0 && r_bottom < y1))
36371 {
36372
36373
36374 if (row->overlapping_p && !row->mode_line_p)
36375 {
36376 if (first_overlapping_row == NULL)
36377 first_overlapping_row = row;
36378 last_overlapping_row = row;
36379 }
36380
36381 row->clip = fr;
36382 if (expose_line (w, row, &r))
36383 mouse_face_overwritten_p = true;
36384 row->clip = NULL;
36385 }
36386 else if (row->overlapping_p)
36387 {
36388
36389 if (y0 < r.y
36390 ? y0 + row->phys_height > r.y
36391 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36392 {
36393 if (first_overlapping_row == NULL)
36394 first_overlapping_row = row;
36395 last_overlapping_row = row;
36396 }
36397 }
36398
36399 if (y1 >= yb)
36400 break;
36401 }
36402
36403 if (buffer_changed)
36404 set_buffer_internal_1 (oldbuf);
36405
36406
36407 if (window_wants_mode_line (w)
36408 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36409 row->enabled_p)
36410 && row->y < r_bottom)
36411 {
36412 if (expose_line (w, row, &r))
36413 mouse_face_overwritten_p = true;
36414 }
36415
36416 if (!w->pseudo_window_p)
36417 {
36418
36419 if (first_overlapping_row)
36420 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36421 fr);
36422
36423
36424 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36425 gui_draw_right_divider (w);
36426 else
36427 gui_draw_vertical_border (w);
36428
36429 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36430 gui_draw_bottom_divider (w);
36431
36432
36433 if (cursor_cleared_p
36434 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36435 update_window_cursor (w, true);
36436 }
36437 }
36438
36439 return mouse_face_overwritten_p;
36440 }
36441
36442
36443
36444
36445
36446
36447
36448 static bool
36449 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36450 {
36451 struct frame *f = XFRAME (w->frame);
36452 bool mouse_face_overwritten_p = false;
36453
36454 while (w && !FRAME_GARBAGED_P (f))
36455 {
36456 mouse_face_overwritten_p
36457 |= (WINDOWP (w->contents)
36458 ? expose_window_tree (XWINDOW (w->contents), r)
36459 : expose_window (w, r));
36460
36461 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36462 }
36463
36464 return mouse_face_overwritten_p;
36465 }
36466
36467
36468
36469
36470
36471
36472
36473
36474 void
36475 expose_frame (struct frame *f, int x, int y, int w, int h)
36476 {
36477 Emacs_Rectangle r;
36478 bool mouse_face_overwritten_p = false;
36479
36480 if (FRAME_GARBAGED_P (f))
36481 {
36482 redisplay_trace ("expose_frame garbaged\n");
36483 return;
36484 }
36485
36486
36487
36488
36489 if (FRAME_FACE_CACHE (f) == NULL
36490 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36491 {
36492 redisplay_trace ("expose_frame no faces\n");
36493 return;
36494 }
36495
36496 if (w == 0 || h == 0)
36497 {
36498 r.x = r.y = 0;
36499 r.width = FRAME_TEXT_WIDTH (f);
36500 r.height = FRAME_TEXT_HEIGHT (f);
36501 }
36502 else
36503 {
36504 r.x = x;
36505 r.y = y;
36506 r.width = w;
36507 r.height = h;
36508 }
36509
36510 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36511 r.x, r.y, r.width, r.height);
36512 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36513
36514 if (WINDOWP (f->tab_bar_window))
36515 mouse_face_overwritten_p
36516 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36517
36518 #ifndef HAVE_EXT_TOOL_BAR
36519 if (WINDOWP (f->tool_bar_window))
36520 mouse_face_overwritten_p
36521 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36522 #endif
36523
36524 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
36525 if (WINDOWP (f->menu_bar_window))
36526 mouse_face_overwritten_p
36527 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36528 #endif
36529
36530
36531
36532
36533
36534
36535
36536
36537
36538
36539
36540
36541
36542
36543 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36544 {
36545 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36546 if (f == hlinfo->mouse_face_mouse_frame)
36547 {
36548 int mouse_x = hlinfo->mouse_face_mouse_x;
36549 int mouse_y = hlinfo->mouse_face_mouse_y;
36550 clear_mouse_face (hlinfo);
36551 note_mouse_highlight (f, mouse_x, mouse_y);
36552 }
36553 }
36554 }
36555
36556
36557
36558
36559
36560
36561
36562 bool
36563 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36564 Emacs_Rectangle *result)
36565 {
36566 const Emacs_Rectangle *left, *right;
36567 const Emacs_Rectangle *upper, *lower;
36568 bool intersection_p = false;
36569
36570
36571 if (r1->x < r2->x)
36572 left = r1, right = r2;
36573 else
36574 left = r2, right = r1;
36575
36576
36577
36578 if (right->x <= left->x + left->width)
36579 {
36580 result->x = right->x;
36581
36582
36583
36584 result->width = (min (left->x + left->width, right->x + right->width)
36585 - result->x);
36586
36587
36588 if (r1->y < r2->y)
36589 upper = r1, lower = r2;
36590 else
36591 upper = r2, lower = r1;
36592
36593
36594
36595 if (lower->y <= upper->y + upper->height)
36596 {
36597 result->y = lower->y;
36598
36599
36600
36601 result->height = (min (lower->y + lower->height,
36602 upper->y + upper->height)
36603 - result->y);
36604 intersection_p = true;
36605 }
36606 }
36607
36608 return intersection_p;
36609 }
36610
36611
36612
36613
36614
36615
36616 void
36617 gui_union_rectangles (const Emacs_Rectangle *a, const Emacs_Rectangle *b,
36618 Emacs_Rectangle *result)
36619 {
36620 struct gui_box a_box, b_box, result_box;
36621
36622
36623
36624 if (!a->width || !a->height)
36625 {
36626 *result = *b;
36627 return;
36628 }
36629 else if (!b->width || !b->height)
36630 {
36631 *result = *a;
36632 return;
36633 }
36634
36635
36636 a_box.x1 = a->x;
36637 a_box.y1 = a->y;
36638 a_box.x2 = a->x + a->width;
36639 a_box.y2 = a->y + a->height;
36640
36641 b_box.x1 = b->x;
36642 b_box.y1 = b->y;
36643 b_box.x2 = b->x + b->width;
36644 b_box.y2 = b->y + b->height;
36645
36646
36647 result_box.x1 = min (a_box.x1, b_box.x1);
36648 result_box.y1 = min (a_box.y1, b_box.y1);
36649 result_box.x2 = max (a_box.x2, b_box.x2);
36650 result_box.y2 = max (a_box.y2, b_box.y2);
36651
36652
36653
36654 result->x = result_box.x1;
36655 result->y = result_box.y1;
36656 result->width = result_box.x2 - result_box.x1;
36657 result->height = result_box.y2 - result_box.y1;
36658 }
36659
36660 #endif
36661
36662
36663
36664
36665
36666
36667 void
36668 syms_of_xdisp (void)
36669 {
36670 Vwith_echo_area_save_vector = Qnil;
36671 staticpro (&Vwith_echo_area_save_vector);
36672
36673 Vmessage_stack = Qnil;
36674 staticpro (&Vmessage_stack);
36675
36676
36677 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36678
36679 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36680
36681 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36682 scroll_minibuffer_conservatively,
36683 doc:
36684
36685 );
36686 scroll_minibuffer_conservatively = true;
36687
36688 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36689 doc:
36690
36691
36692
36693
36694
36695 );
36696 inhibit_message = false;
36697
36698 message_dolog_marker1 = Fmake_marker ();
36699 staticpro (&message_dolog_marker1);
36700 message_dolog_marker2 = Fmake_marker ();
36701 staticpro (&message_dolog_marker2);
36702 message_dolog_marker3 = Fmake_marker ();
36703 staticpro (&message_dolog_marker3);
36704
36705 defsubr (&Sset_buffer_redisplay);
36706 #ifdef GLYPH_DEBUG
36707 defsubr (&Sdump_frame_glyph_matrix);
36708 defsubr (&Sdump_glyph_matrix);
36709 defsubr (&Sdump_glyph_row);
36710 defsubr (&Sdump_tab_bar_row);
36711 defsubr (&Sdump_tool_bar_row);
36712 defsubr (&Strace_redisplay);
36713 defsubr (&Strace_to_stderr);
36714 #endif
36715 #ifdef HAVE_WINDOW_SYSTEM
36716 defsubr (&Stab_bar_height);
36717 defsubr (&Stool_bar_height);
36718 defsubr (&Slookup_image_map);
36719 #endif
36720 defsubr (&Sline_pixel_height);
36721 defsubr (&Sformat_mode_line);
36722 defsubr (&Sinvisible_p);
36723 defsubr (&Scurrent_bidi_paragraph_direction);
36724 defsubr (&Swindow_text_pixel_size);
36725 defsubr (&Sbuffer_text_pixel_size);
36726 defsubr (&Smove_point_visually);
36727 defsubr (&Sbidi_find_overridden_directionality);
36728 defsubr (&Sdisplay__line_is_continued_p);
36729 defsubr (&Sget_display_property);
36730 defsubr (&Slong_line_optimizations_p);
36731
36732 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36733 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36734 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36735 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36736 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36737 DEFSYM (Qeval, "eval");
36738 DEFSYM (QCdata, ":data");
36739
36740
36741 DEFSYM (Qdisplay, "display");
36742 DEFSYM (Qspace_width, "space-width");
36743 DEFSYM (Qraise, "raise");
36744 DEFSYM (Qslice, "slice");
36745 DEFSYM (Qspace, "space");
36746 DEFSYM (Qmargin, "margin");
36747 DEFSYM (Qpointer, "pointer");
36748 DEFSYM (Qleft_margin, "left-margin");
36749 DEFSYM (Qright_margin, "right-margin");
36750 DEFSYM (Qcenter, "center");
36751 DEFSYM (Qline_height, "line-height");
36752 DEFSYM (QCalign_to, ":align-to");
36753 DEFSYM (QCrelative_width, ":relative-width");
36754 DEFSYM (QCrelative_height, ":relative-height");
36755 DEFSYM (QCeval, ":eval");
36756 DEFSYM (QCpropertize, ":propertize");
36757 DEFSYM (QCfile, ":file");
36758 DEFSYM (Qfontified, "fontified");
36759 DEFSYM (Qfontification_functions, "fontification-functions");
36760 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36761 "long-line-optimizations-in-fontification-functions");
36762
36763
36764
36765 DEFSYM (Qdisable_eval, "disable-eval");
36766
36767
36768 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36769
36770
36771 DEFSYM (Qline_number, "line-number");
36772 DEFSYM (Qline_number_current_line, "line-number-current-line");
36773 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36774 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36775
36776 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36777
36778
36779 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36780
36781
36782 DEFSYM (Qescape_glyph, "escape-glyph");
36783
36784
36785
36786 DEFSYM (Qnobreak_space, "nobreak-space");
36787 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36788
36789
36790
36791 DEFSYM (Qimage, "image");
36792
36793
36794 DEFSYM (Qtext, "text");
36795 DEFSYM (Qboth, "both");
36796 DEFSYM (Qboth_horiz, "both-horiz");
36797 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36798
36799
36800 DEFSYM (QCmap, ":map");
36801 DEFSYM (QCpointer, ":pointer");
36802 DEFSYM (Qrect, "rect");
36803 DEFSYM (Qcircle, "circle");
36804 DEFSYM (Qpoly, "poly");
36805
36806 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36807
36808 DEFSYM (Qgrow_only, "grow-only");
36809 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36810 DEFSYM (Qposition, "position");
36811 DEFSYM (Qbuffer_position, "buffer-position");
36812 DEFSYM (Qobject, "object");
36813
36814
36815 DEFSYM (Qbar, "bar");
36816 DEFSYM (Qhbar, "hbar");
36817 DEFSYM (Qbox, "box");
36818 DEFSYM (Qhollow, "hollow");
36819
36820
36821 DEFSYM (Qhand, "hand");
36822 DEFSYM (Qarrow, "arrow");
36823
36824
36825 DEFSYM (Qdragging, "dragging");
36826 DEFSYM (Qdropping, "dropping");
36827 DEFSYM (Qdrag_source, "drag-source");
36828
36829 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36830 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36831 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36832
36833 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36834
36835 list_of_error = list1 (Qerror);
36836 staticpro (&list_of_error);
36837
36838
36839
36840
36841
36842 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36843 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36844
36845
36846
36847 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36848 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36849
36850 echo_buffer[0] = echo_buffer[1] = Qnil;
36851 staticpro (&echo_buffer[0]);
36852 staticpro (&echo_buffer[1]);
36853
36854 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36855 staticpro (&echo_area_buffer[0]);
36856 staticpro (&echo_area_buffer[1]);
36857
36858 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36859 doc:
36860
36861
36862
36863 );
36864 Vmessages_buffer_name = build_string ("*Messages*");
36865
36866 mode_line_proptrans_alist = Qnil;
36867 staticpro (&mode_line_proptrans_alist);
36868 mode_line_string_list = Qnil;
36869 staticpro (&mode_line_string_list);
36870 mode_line_string_face = Qnil;
36871 staticpro (&mode_line_string_face);
36872 mode_line_string_face_prop = Qnil;
36873 staticpro (&mode_line_string_face_prop);
36874 Vmode_line_unwind_vector = Qnil;
36875 staticpro (&Vmode_line_unwind_vector);
36876
36877 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36878
36879 help_echo_string = Qnil;
36880 staticpro (&help_echo_string);
36881 help_echo_object = Qnil;
36882 staticpro (&help_echo_object);
36883 help_echo_window = Qnil;
36884 staticpro (&help_echo_window);
36885 previous_help_echo_string = Qnil;
36886 staticpro (&previous_help_echo_string);
36887 help_echo_pos = -1;
36888
36889 DEFSYM (Qright_to_left, "right-to-left");
36890 DEFSYM (Qleft_to_right, "left-to-right");
36891 defsubr (&Sbidi_resolved_levels);
36892
36893 #ifdef HAVE_WINDOW_SYSTEM
36894 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36895 doc:
36896
36897 );
36898 x_stretch_cursor_p = 0;
36899 #endif
36900
36901 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36902 doc:
36903 );
36904 Vshow_trailing_whitespace = Qnil;
36905
36906 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36907 doc:
36908
36909
36910 );
36911 Vmode_line_compact = Qnil;
36912 DEFSYM (Qlong, "long");
36913
36914 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36915 doc:
36916
36917
36918
36919
36920
36921
36922
36923
36924
36925
36926
36927 );
36928 Vnobreak_char_display = Qt;
36929
36930 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36931 doc:
36932
36933
36934
36935
36936
36937
36938
36939
36940
36941
36942
36943
36944
36945
36946
36947 );
36948 nobreak_char_ascii_display = false;
36949
36950 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36951 doc:
36952
36953
36954 );
36955 Vvoid_text_area_pointer = Qarrow;
36956
36957 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36958 doc:
36959 );
36960 Vinhibit_redisplay = Qnil;
36961
36962 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36963 doc: );
36964 Vglobal_mode_string = Qnil;
36965
36966 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
36967 doc:
36968
36969 );
36970 Voverlay_arrow_position = Qnil;
36971
36972 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
36973 doc:
36974 );
36975 Voverlay_arrow_string = build_pure_c_string ("=>");
36976
36977 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
36978 doc:
36979
36980 );
36981 Voverlay_arrow_variable_list
36982 = list1 (intern_c_string ("overlay-arrow-position"));
36983
36984 DEFVAR_INT ("scroll-step", emacs_scroll_step,
36985 doc:
36986
36987
36988
36989 );
36990
36991 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
36992 doc:
36993
36994
36995
36996
36997
36998
36999
37000
37001
37002 );
37003 scroll_conservatively = 0;
37004
37005 DEFVAR_INT ("scroll-margin", scroll_margin,
37006 doc:
37007
37008 );
37009 scroll_margin = 0;
37010
37011 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
37012 doc:
37013
37014
37015
37016 );
37017 Vmaximum_scroll_margin = make_float (0.25);
37018
37019 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
37020 doc:
37021 );
37022 Vdisplay_pixels_per_inch = make_float (72.0);
37023
37024 #ifdef GLYPH_DEBUG
37025 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
37026 #endif
37027
37028 DEFVAR_LISP ("truncate-partial-width-windows",
37029 Vtruncate_partial_width_windows,
37030 doc:
37031
37032
37033
37034
37035
37036
37037
37038
37039
37040
37041
37042
37043
37044
37045
37046 );
37047 Vtruncate_partial_width_windows = make_fixnum (50);
37048
37049 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
37050
37051
37052
37053
37054
37055
37056
37057
37058
37059
37060
37061
37062
37063 );
37064 word_wrap_by_category = false;
37065
37066 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
37067 doc:
37068
37069 );
37070 Vline_number_display_limit = Qnil;
37071
37072 DEFVAR_INT ("line-number-display-limit-width",
37073 line_number_display_limit_width,
37074 doc:
37075
37076 );
37077 line_number_display_limit_width = 200;
37078
37079 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
37080 doc:
37081
37082 );
37083 highlight_nonselected_windows = false;
37084
37085 DEFVAR_BOOL ("multiple-frames", multiple_frames,
37086 doc:
37087
37088
37089 );
37090
37091 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
37092 doc:
37093
37094
37095
37096
37097 );
37098
37099 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
37100 doc:
37101
37102
37103
37104
37105
37106 );
37107
37108
37109 Lisp_Object icon_title_name_format
37110 = pure_list (empty_unibyte_string,
37111 build_pure_c_string ("%b - GNU Emacs at "),
37112 intern_c_string ("system-name"));
37113 Vicon_title_format
37114 = Vframe_title_format
37115 = pure_list (intern_c_string ("multiple-frames"),
37116 build_pure_c_string ("%b"),
37117 icon_title_name_format);
37118
37119 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
37120 doc:
37121
37122 );
37123 Vmessage_log_max = make_fixnum (1000);
37124
37125 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
37126 doc:
37127
37128
37129
37130
37131
37132
37133
37134
37135
37136
37137
37138
37139
37140 );
37141 Vwindow_scroll_functions = Qnil;
37142
37143 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
37144 doc:
37145
37146
37147
37148
37149
37150
37151
37152
37153
37154
37155
37156
37157
37158
37159
37160
37161
37162 );
37163 Vmouse_autoselect_window = Qnil;
37164
37165 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
37166 doc:
37167
37168
37169
37170
37171 );
37172 Vauto_resize_tab_bars = Qt;
37173
37174 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
37175 doc: );
37176 auto_raise_tab_bar_buttons_p = true;
37177
37178 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
37179 doc:
37180
37181
37182
37183
37184 );
37185 Vauto_resize_tool_bars = Qt;
37186
37187 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
37188 doc: );
37189 auto_raise_tool_bar_buttons_p = true;
37190
37191 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
37192 doc:
37193
37194
37195
37196
37197 );
37198 Vmake_cursor_line_fully_visible = Qt;
37199 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
37200
37201 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
37202 doc: );
37203 make_window_start_visible = false;
37204 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
37205 Fmake_variable_buffer_local (Qmake_window_start_visible);
37206
37207 DEFSYM (Qclose_tab, "close-tab");
37208 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
37209 doc:
37210
37211
37212
37213 );
37214 Vtab_bar_border = Qinternal_border_width;
37215
37216 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
37217 doc:
37218
37219
37220
37221 );
37222 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
37223
37224 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
37225 doc: );
37226 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
37227
37228 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
37229 doc:
37230
37231
37232
37233 );
37234 Vtool_bar_border = Qinternal_border_width;
37235
37236 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
37237 doc:
37238
37239
37240
37241 );
37242 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
37243
37244 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
37245 doc: );
37246 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
37247
37248 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
37249 doc:
37250
37251
37252
37253
37254
37255
37256
37257
37258 );
37259 Vtool_bar_style = Qnil;
37260
37261 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
37262 doc:
37263
37264 );
37265 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
37266
37267 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
37268 doc:
37269
37270
37271
37272
37273
37274
37275
37276
37277 );
37278 Vfontification_functions = Qnil;
37279 Fmake_variable_buffer_local (Qfontification_functions);
37280
37281 DEFVAR_BOOL ("unibyte-display-via-language-environment",
37282 unibyte_display_via_language_environment,
37283 doc:
37284
37285
37286
37287
37288
37289
37290 );
37291 unibyte_display_via_language_environment = false;
37292
37293 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
37294 doc:
37295
37296
37297
37298 );
37299 Vmax_mini_window_height = make_float (0.25);
37300
37301 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37302 doc:
37303
37304
37305
37306
37307
37308
37309
37310
37311 );
37312
37313
37314
37315
37316
37317 Vresize_mini_windows = Qnil;
37318
37319 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37320 doc:
37321
37322
37323
37324
37325
37326
37327
37328 );
37329 Vblink_cursor_alist = Qnil;
37330
37331 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37332 doc:
37333
37334
37335
37336 );
37337 automatic_hscrolling = Qt;
37338 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37339 DEFSYM (Qcurrent_line, "current-line");
37340
37341 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37342 doc:
37343 );
37344 hscroll_margin = 5;
37345
37346 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37347 doc:
37348
37349
37350
37351
37352
37353
37354
37355
37356
37357
37358
37359
37360
37361 );
37362 Vhscroll_step = make_fixnum (0);
37363
37364 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37365 doc:
37366 );
37367 message_truncate_lines = false;
37368
37369 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37370 doc:
37371
37372
37373 );
37374 Vmenu_bar_update_hook = Qnil;
37375
37376 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37377 doc:
37378 );
37379 Vmenu_updating_frame = Qnil;
37380
37381 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37382 doc: );
37383 inhibit_menubar_update = false;
37384
37385 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37386 doc:
37387
37388
37389
37390
37391
37392
37393 );
37394 Vwrap_prefix = Qnil;
37395 DEFSYM (Qwrap_prefix, "wrap-prefix");
37396 Fmake_variable_buffer_local (Qwrap_prefix);
37397
37398 DEFVAR_LISP ("line-prefix", Vline_prefix,
37399 doc:
37400
37401
37402
37403
37404
37405
37406 );
37407 Vline_prefix = Qnil;
37408 DEFSYM (Qline_prefix, "line-prefix");
37409 Fmake_variable_buffer_local (Qline_prefix);
37410
37411 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37412 doc:
37413
37414
37415
37416
37417
37418
37419
37420
37421
37422
37423
37424
37425
37426
37427
37428
37429
37430
37431
37432
37433
37434
37435 );
37436 Vdisplay_line_numbers = Qnil;
37437 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37438 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37439 DEFSYM (Qrelative, "relative");
37440 DEFSYM (Qvisual, "visual");
37441
37442 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37443 doc:
37444
37445
37446
37447 );
37448 Vdisplay_line_numbers_width = Qnil;
37449 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37450 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37451
37452 DEFVAR_LISP ("display-line-numbers-current-absolute",
37453 Vdisplay_line_numbers_current_absolute,
37454 doc:
37455
37456 );
37457 Vdisplay_line_numbers_current_absolute = Qt;
37458
37459 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37460 doc: );
37461 display_line_numbers_widen = false;
37462 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37463 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37464
37465 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37466 doc:
37467
37468
37469 );
37470 display_line_numbers_offset = 0;
37471 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37472 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37473
37474 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37475 doc:
37476
37477
37478 );
37479 display_fill_column_indicator = false;
37480 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37481 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37482
37483 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37484 doc:
37485
37486
37487
37488 );
37489 Vdisplay_fill_column_indicator_column = Qt;
37490 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37491 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37492
37493 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37494 doc:
37495
37496
37497 );
37498 Vdisplay_fill_column_indicator_character = Qnil;
37499 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37500 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37501
37502 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37503 doc:
37504
37505
37506 );
37507 display_line_numbers_major_tick = 0;
37508
37509 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37510 doc:
37511
37512
37513 );
37514 display_line_numbers_minor_tick = 0;
37515
37516 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37517 doc: );
37518 inhibit_eval_during_redisplay = false;
37519
37520 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37521 doc: );
37522 inhibit_free_realized_faces = false;
37523
37524 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37525 doc:
37526
37527 );
37528 inhibit_bidi_mirroring = false;
37529
37530 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37531 doc:
37532
37533
37534
37535 );
37536 bidi_inhibit_bpa = false;
37537
37538 #ifdef GLYPH_DEBUG
37539 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37540 doc: );
37541 inhibit_try_window_id = false;
37542
37543 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37544 doc: );
37545 inhibit_try_window_reusing = false;
37546
37547 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37548 doc: );
37549 inhibit_try_cursor_movement = false;
37550 #endif
37551
37552 DEFVAR_INT ("overline-margin", overline_margin,
37553 doc:
37554
37555 );
37556 overline_margin = 2;
37557
37558 DEFVAR_INT ("underline-minimum-offset",
37559 underline_minimum_offset,
37560 doc:
37561
37562
37563
37564 );
37565 underline_minimum_offset = 1;
37566 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37567
37568 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37569 doc:
37570
37571 );
37572 display_hourglass_p = true;
37573
37574 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37575 doc: );
37576 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37577
37578 #ifdef HAVE_WINDOW_SYSTEM
37579 hourglass_atimer = NULL;
37580 hourglass_shown_p = false;
37581 #endif
37582
37583
37584 DEFSYM (Qglyphless_char, "glyphless-char");
37585
37586
37587 DEFSYM (Qhex_code, "hex-code");
37588 DEFSYM (Qempty_box, "empty-box");
37589 DEFSYM (Qthin_space, "thin-space");
37590 DEFSYM (Qzero_width, "zero-width");
37591
37592 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37593 doc:
37594
37595
37596 );
37597 Vpre_redisplay_function = intern ("ignore");
37598
37599
37600 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37601 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37602
37603 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37604 doc:
37605
37606
37607
37608
37609
37610
37611
37612
37613
37614
37615
37616
37617
37618
37619
37620
37621
37622
37623
37624
37625
37626
37627
37628 );
37629 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37630 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37631 Qempty_box);
37632
37633 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37634 doc: );
37635 Vdebug_on_message = Qnil;
37636
37637 DEFVAR_LISP ("set-message-function", Vset_message_function,
37638 doc:
37639
37640
37641
37642
37643
37644
37645
37646
37647
37648 );
37649 Vset_message_function = Qnil;
37650
37651 DEFSYM (Qdont_clear_message, "dont-clear-message");
37652 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37653 doc:
37654
37655
37656
37657
37658
37659
37660
37661
37662
37663
37664 );
37665 Vclear_message_function = Qnil;
37666
37667 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37668 doc:
37669 );
37670 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37671
37672 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37673 doc:
37674 );
37675 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37676
37677 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37678 doc: );
37679
37680
37681 redisplay__inhibit_bidi = true;
37682
37683 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37684 doc:
37685
37686 );
37687 display_raw_bytes_as_hex = false;
37688
37689 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37690 doc:
37691
37692 );
37693 mouse_fine_grained_tracking = false;
37694
37695 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37696 doc: );
37697 tab_bar__dragging_in_progress = false;
37698
37699 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37700 doc:
37701
37702
37703
37704 );
37705 redisplay_skip_initial_frame = true;
37706
37707 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37708 redisplay_skip_fontification_on_input,
37709 doc:
37710
37711
37712
37713
37714
37715
37716
37717 );
37718 redisplay_skip_fontification_on_input = false;
37719
37720 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37721 redisplay_adhoc_scroll_in_resize_mini_windows,
37722 doc:
37723
37724 );
37725
37726 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37727
37728 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37729 doc:
37730
37731 );
37732 composition_break_at_point = false;
37733
37734 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37735 doc:
37736
37737
37738
37739
37740
37741
37742
37743
37744
37745
37746
37747 );
37748 max_redisplay_ticks = 0;
37749 }
37750
37751
37752
37753
37754 void
37755 init_xdisp (void)
37756 {
37757 CHARPOS (this_line_start_pos) = 0;
37758
37759 echo_area_window = minibuf_window;
37760
37761 if (!noninteractive)
37762 {
37763 struct window *m = XWINDOW (minibuf_window);
37764 Lisp_Object frame = m->frame;
37765 struct frame *f = XFRAME (frame);
37766 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37767 struct window *r = XWINDOW (root);
37768 int i;
37769
37770 r->top_line = FRAME_TOP_MARGIN (f);
37771 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37772 r->total_cols = FRAME_COLS (f);
37773 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37774 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_MARGINS (f);
37775 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37776
37777 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37778 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37779 m->total_cols = FRAME_COLS (f);
37780 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37781 m->total_lines = 1;
37782 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37783
37784 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37785 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37786 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37787
37788
37789 for (i = 0; i < 3; ++i)
37790 default_invis_vector[i] = make_fixnum ('.');
37791 }
37792
37793 {
37794
37795
37796 int size = 100;
37797 mode_line_noprop_buf = xmalloc (size);
37798 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37799 mode_line_noprop_ptr = mode_line_noprop_buf;
37800 mode_line_target = MODE_LINE_DISPLAY;
37801 }
37802
37803 help_echo_showing_p = false;
37804 }
37805
37806 #ifdef HAVE_WINDOW_SYSTEM
37807
37808
37809
37810
37811
37812 static void
37813 show_hourglass (struct atimer *timer)
37814 {
37815
37816
37817
37818 hourglass_atimer = NULL;
37819
37820 if (!hourglass_shown_p)
37821 {
37822 Lisp_Object tail, frame;
37823
37824 block_input ();
37825
37826 FOR_EACH_FRAME (tail, frame)
37827 {
37828 struct frame *f = XFRAME (frame);
37829
37830 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37831 && FRAME_RIF (f)->show_hourglass)
37832 FRAME_RIF (f)->show_hourglass (f);
37833 }
37834
37835 hourglass_shown_p = true;
37836 unblock_input ();
37837 }
37838 }
37839
37840
37841
37842 void
37843 start_hourglass (void)
37844 {
37845 struct timespec delay;
37846
37847 cancel_hourglass ();
37848
37849 if (FIXNUMP (Vhourglass_delay)
37850 && XFIXNUM (Vhourglass_delay) > 0)
37851 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37852 TYPE_MAXIMUM (time_t)),
37853 0);
37854 else if (FLOATP (Vhourglass_delay)
37855 && XFLOAT_DATA (Vhourglass_delay) > 0)
37856 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37857 else
37858 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37859
37860 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37861 show_hourglass, NULL);
37862 }
37863
37864
37865
37866
37867 void
37868 cancel_hourglass (void)
37869 {
37870 if (hourglass_atimer)
37871 {
37872 cancel_atimer (hourglass_atimer);
37873 hourglass_atimer = NULL;
37874 }
37875
37876 if (hourglass_shown_p)
37877 {
37878 Lisp_Object tail, frame;
37879
37880 block_input ();
37881
37882 FOR_EACH_FRAME (tail, frame)
37883 {
37884 struct frame *f = XFRAME (frame);
37885
37886 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37887 && FRAME_RIF (f)->hide_hourglass)
37888 FRAME_RIF (f)->hide_hourglass (f);
37889 #ifdef HAVE_NTGUI
37890
37891 else if (!FRAME_W32_P (f))
37892 w32_arrow_cursor ();
37893 #endif
37894 }
37895
37896 hourglass_shown_p = false;
37897 unblock_input ();
37898 }
37899 }
37900
37901
37902
37903
37904
37905
37906
37907
37908 static int
37909 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37910 struct window *w,
37911 struct face *original_face,
37912 struct face *mouse_face)
37913 {
37914 int sum = 0;
37915
37916 bool do_left_box_p = g->left_box_line_p;
37917 bool do_right_box_p = g->right_box_line_p;
37918
37919
37920
37921 if (g->type == IMAGE_GLYPH)
37922 {
37923 if (!row->reversed_p)
37924 {
37925 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37926 g->u.img_id);
37927 do_left_box_p = g->left_box_line_p &&
37928 g->slice.img.x == 0;
37929 do_right_box_p = g->right_box_line_p &&
37930 g->slice.img.x + g->slice.img.width == img->width;
37931 }
37932 else
37933 {
37934 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37935 g->u.img_id);
37936 do_left_box_p = g->left_box_line_p &&
37937 g->slice.img.x + g->slice.img.width == img->width;
37938 do_right_box_p = g->right_box_line_p &&
37939 g->slice.img.x == 0;
37940 }
37941 }
37942
37943
37944 if (do_left_box_p)
37945 sum -= max (0, original_face->box_vertical_line_width);
37946
37947
37948 if (do_right_box_p)
37949 sum -= max (0, original_face->box_vertical_line_width);
37950
37951 if (g->left_box_line_p)
37952 sum += max (0, mouse_face->box_vertical_line_width);
37953 if (g->right_box_line_p)
37954 sum += max (0, mouse_face->box_vertical_line_width);
37955
37956 return sum;
37957 }
37958
37959
37960
37961
37962
37963
37964
37965
37966
37967 static void
37968 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
37969 int *offset)
37970 {
37971 int sum = 0;
37972
37973 if (row->mode_line_p)
37974 return;
37975
37976 block_input ();
37977
37978 struct frame *f = WINDOW_XFRAME (w);
37979 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
37980 struct glyph *start, *end;
37981 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
37982 int hpos = w->phys_cursor.hpos;
37983 end = &row->glyphs[TEXT_AREA][hpos];
37984
37985 if (!row->reversed_p)
37986 {
37987 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37988 hlinfo->mouse_face_beg_row)
37989 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
37990 else
37991 start = row->glyphs[TEXT_AREA];
37992 }
37993 else
37994 {
37995 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37996 hlinfo->mouse_face_end_row)
37997 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
37998 else
37999 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
38000 }
38001
38002
38003
38004
38005 for ( ; row->reversed_p ? start > end : start < end;
38006 row->reversed_p ? --start : ++start)
38007 sum += adjust_glyph_width_for_mouse_face (start, row, w,
38008 FACE_FROM_ID (f, start->face_id),
38009 mouse_face);
38010
38011 if (row->reversed_p)
38012 sum = -sum;
38013
38014 *offset = sum;
38015
38016 unblock_input ();
38017 }
38018 #endif